示例#1
0
文件: ogenmap.cpp 项目: mecirt/7k2
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
			}
		}
	}
}