void World::set_tera_height(Plasma &plasma) { memset(corner_matrix, 0, sizeof(Corner)*(max_x_loc+1)*(max_y_loc+1)); // short seaHeight = TerrainRes::max_height(TERRAIN_OCEAN); short seaHeight = 0; // no more sea int y; int x; for(y = 0; y <= max_y_loc; ++y ) { for(x = 0; x <= max_x_loc; ++x) { Corner *cornerPtr = get_corner(x,y); cornerPtr->set_altitude(plasma.get_pix(x,y)); cornerPtr->set_sea_altitude(seaHeight); // set gradient_x float gradientX; if(x <= 0) { err_when(x < 0); gradientX = float(4*plasma.get_pix(x+1,y) - plasma.get_pix(x+2,y) - 3*plasma.get_pix(x,y)) / (2 * LOCATE_WIDTH); } else if( x >= max_x_loc ) { err_when(x > max_x_loc); gradientX = float(plasma.get_pix(x-2,y) - 4*plasma.get_pix(x-1,y) + 3*plasma.get_pix(x,y)) / (2 * LOCATE_WIDTH); } else { gradientX = float(plasma.get_pix(x+1,y) - plasma.get_pix(x-1,y)) / (2 * LOCATE_WIDTH); } // if( gradientX >= 0.0f && gradientX <= 0.25f ) // gradientX += 0.15f; // else if( gradientX < 0.0f && gradientX >= -0.25f ) // gradientX -= 0.15f; cornerPtr->set_gradient_x( gradientX ); // set gradient_y float gradientY; if(y <= 0) { err_when(y < 0); gradientY = float(4*plasma.get_pix(x,y+1) - plasma.get_pix(x,y+2) - 3*plasma.get_pix(x,y)) / (2 * LOCATE_HEIGHT); } else if( y >= max_y_loc ) { err_when(y > max_y_loc); gradientY = float(plasma.get_pix(x,y-2) - 4*plasma.get_pix(x,y-1) + 3*plasma.get_pix(x,y)) / (2 * LOCATE_HEIGHT); } else { gradientY = float(plasma.get_pix(x,y+1) - plasma.get_pix(x,y-1)) / (2 * LOCATE_HEIGHT); } // if( gradientY >= 0.0f && gradientY <= 0.25f ) // gradientY += 0.15f; // else if( gradientY < 0.0f && gradientY >= -0.25f ) // gradientY -= 0.15f; cornerPtr->set_gradient_y( gradientY ); } } // calculate polynomial coefficient for(y = 0; y < max_y_loc; ++y ) { for(x = 0; x < max_x_loc; ++x) { LocationCorners lc; get_loc_corner(x,y, &lc); short &z0 = lc.top_left->altitude; short &z1 = lc.top_right->altitude; short &z2 = lc.bottom_left->altitude; short &z3 = lc.bottom_right->altitude; short &duz0w = lc.top_left->gradient_x; // du/dz * LOCATE_WIDTH short &dvz0h = lc.top_left->gradient_y; short &duz1w = lc.top_right->gradient_x; short &dvz1h = lc.top_right->gradient_y; short &duz2w = lc.bottom_left->gradient_x; short &dvz2h = lc.bottom_left->gradient_y; short &duz3w = lc.bottom_right->gradient_x; short &dvz3h = lc.bottom_right->gradient_y; lc.loc_ptr->c30 = (duz1w + duz0w - (z1-z0) * 2) << (C_MULTIPLIER_SHIFT - LOCATE_WIDTH_SHIFT - LOCATE_WIDTH_SHIFT - LOCATE_WIDTH_SHIFT); lc.loc_ptr->c21 = (duz3w + duz0w - duz1w - duz2w) << (C_MULTIPLIER_SHIFT - 1 - LOCATE_WIDTH_SHIFT - LOCATE_WIDTH_SHIFT - LOCATE_HEIGHT_SHIFT); lc.loc_ptr->c12 = (dvz3h + dvz0h - dvz1h - dvz2h) << (C_MULTIPLIER_SHIFT - 1 - LOCATE_WIDTH_SHIFT - LOCATE_HEIGHT_SHIFT - LOCATE_HEIGHT_SHIFT); lc.loc_ptr->c03 = (dvz2h + dvz0h - (z2-z0) * 2) << (C_MULTIPLIER_SHIFT - LOCATE_HEIGHT_SHIFT - LOCATE_HEIGHT_SHIFT - LOCATE_HEIGHT_SHIFT); lc.loc_ptr->c20 = ( (z1-z0) * 3 - duz1w - duz0w * 2 ) << (C_MULTIPLIER_SHIFT - LOCATE_WIDTH_SHIFT - LOCATE_WIDTH_SHIFT); lc.loc_ptr->c11 = (( z3 + z0 - z1 - z2 ) << (C_MULTIPLIER_SHIFT - LOCATE_WIDTH_SHIFT - LOCATE_HEIGHT_SHIFT)) - (lc.loc_ptr->c21 << LOCATE_WIDTH_SHIFT) - (lc.loc_ptr->c12 << LOCATE_HEIGHT_SHIFT); lc.loc_ptr->c02 = ( (z2-z0) * 3 - dvz2h - dvz0h * 2 ) << (C_MULTIPLIER_SHIFT - LOCATE_HEIGHT_SHIFT - LOCATE_HEIGHT_SHIFT); lc.loc_ptr->c00 = z0 << C_MULTIPLIER_SHIFT; lc.loc_ptr->c10 = duz0w << (C_MULTIPLIER_SHIFT - LOCATE_WIDTH_SHIFT); lc.loc_ptr->c01 = dvz0h << (C_MULTIPLIER_SHIFT - LOCATE_HEIGHT_SHIFT); // find the height of the rendered bitmap { lc.loc_ptr->min_y = 0; lc.loc_ptr->max_y = 0; int seaLevel = 0; if( lc.top_left->is_sea() ) seaLevel = lc.top_left->sea_altitude; if( lc.top_right->is_sea() ) seaLevel = lc.top_right->sea_altitude; if( lc.bottom_left->is_sea() ) seaLevel = lc.bottom_left->sea_altitude; if( lc.bottom_right->is_sea() ) seaLevel = lc.bottom_right->sea_altitude; if( seaLevel ) lc.loc_ptr->loc_flag |= LOCATE_SEA_COAST; else lc.loc_ptr->loc_flag &= ~LOCATE_SEA_COAST; // height relative to top left corner // int refHeight = ZoomMatrix::calc_abs_y(0, 0, lc.loc_ptr->evaluate_z(0, 0)); int refHeight = ZoomMatrix::calc_abs_y(0, 0, lc.loc_ptr->c00 >> C_MULTIPLIER_SHIFT); // include LOCATE_WIDTH, LOCATE_HEIGHT for wider min_y, max_y for(int v = 0; v <= LOCATE_HEIGHT; v+=LOCATE_HEIGHT/4 ) { for( int u = 0; u <= LOCATE_WIDTH; u+=LOCATE_WIDTH/4 ) { long z = lc.loc_ptr->evaluate_z(u, v); // if cover by sea if( seaLevel && z < seaLevel ) z = seaLevel; int pointY = ZoomMatrix::calc_abs_y(u, v, z) - refHeight; //(z - z0) * ZOOM_Z_HEIGHT //+ (u * ZOOM_LOC_X_HEIGHT * LOCATE_HEIGHT //+ v * ZOOM_LOC_Y_HEIGHT * LOCATE_WIDTH ) //>> (LOCATE_WIDTH_SHIFT + LOCATE_HEIGHT_SHIFT); if( pointY < lc.loc_ptr->min_y) lc.loc_ptr->min_y = pointY; if( pointY > lc.loc_ptr->max_y) lc.loc_ptr->max_y = pointY; } } lc.loc_ptr->min_y -= 8; // -4 for more space lc.loc_ptr->max_y += 8; // +4 for more space } } } }