Пример #1
0
/**
 * Base Perlin noise generator - fills height map with raw Perlin noise.
 *
 * This runs several iterations with increasing precision; the last iteration looks at areas
 * of 1 by 1 tiles, the second to last at 2 by 2 tiles and the initial 2**MAX_TGP_FREQUENCIES
 * by 2**MAX_TGP_FREQUENCIES tiles.
 */
static void HeightMapGenerate()
{
	/* Trying to apply noise to uninitialized height map */
	assert(_height_map.h != NULL);

	int start = max(MAX_TGP_FREQUENCIES - (int)min(MapLogX(), MapLogY()), 0);
	bool first = true;

	for (int frequency = start; frequency < MAX_TGP_FREQUENCIES; frequency++) {
		const amplitude_t amplitude = GetAmplitude(frequency);

		/* Ignore zero amplitudes; it means our map isn't height enough for this
		 * amplitude, so ignore it and continue with the next set of amplitude. */
		if (amplitude == 0) continue;

		const int step = 1 << (MAX_TGP_FREQUENCIES - frequency - 1);

		if (first) {
			/* This is first round, we need to establish base heights with step = size_min */
			for (int y = 0; y <= _height_map.size_y; y += step) {
				for (int x = 0; x <= _height_map.size_x; x += step) {
					height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
					_height_map.height(x, y) = height;
				}
			}
			first = false;
			continue;
		}

		/* It is regular iteration round.
		 * Interpolate height values at odd x, even y tiles */
		for (int y = 0; y <= _height_map.size_y; y += 2 * step) {
			for (int x = 0; x <= _height_map.size_x - 2 * step; x += 2 * step) {
				height_t h00 = _height_map.height(x + 0 * step, y);
				height_t h02 = _height_map.height(x + 2 * step, y);
				height_t h01 = (h00 + h02) / 2;
				_height_map.height(x + 1 * step, y) = h01;
			}
		}

		/* Interpolate height values at odd y tiles */
		for (int y = 0; y <= _height_map.size_y - 2 * step; y += 2 * step) {
			for (int x = 0; x <= _height_map.size_x; x += step) {
				height_t h00 = _height_map.height(x, y + 0 * step);
				height_t h20 = _height_map.height(x, y + 2 * step);
				height_t h10 = (h00 + h20) / 2;
				_height_map.height(x, y + 1 * step) = h10;
			}
		}

		/* Add noise for next higher frequency (smaller steps) */
		for (int y = 0; y <= _height_map.size_y; y += step) {
			for (int x = 0; x <= _height_map.size_x; x += step) {
				_height_map.height(x, y) += RandomHeight(amplitude);
			}
		}
	}
}
Пример #2
0
/**
 * One interpolation and noise round
 *
 * The heights on the map are generated in an iterative process.
 * We start off with a frequency of 1 (log_frequency == 0), and generate heights only for corners on the most coarsly mesh
 * (i.e. only for x/y coordinates which are multiples of the minimum edge length).
 *
 * After this initial step the frequency is doubled (log_frequency incremented) each iteration to generate corners on the next finer mesh.
 * The heights of the newly added corners are first set by interpolating the heights from the previous iteration.
 * Finally noise with the given amplitude is applied to all corners of the new mesh.
 *
 * Generation terminates, when the frequency has reached the map size. I.e. the mesh is as fine as the map, and every corner height
 * has been set.
 *
 * @param log_frequency frequency (logarithmic) to apply noise for
 * @param amplitude Amplitude for the noise
 * @return false if we are finished (reached the minimal step size / highest frequency)
 */
static bool ApplyNoise(uint log_frequency, amplitude_t amplitude)
{
	uint size_min = min(_height_map.size_x, _height_map.size_y);
	uint step = size_min >> log_frequency;
	uint x, y;

	/* Trying to apply noise to uninitialized height map */
	assert(_height_map.h != NULL);

	/* Are we finished? */
	if (step == 0) return false;

	if (log_frequency == 0) {
		/* This is first round, we need to establish base heights with step = size_min */
		for (y = 0; y <= _height_map.size_y; y += step) {
			for (x = 0; x <= _height_map.size_x; x += step) {
				height_t height = (amplitude > 0) ? RandomHeight(amplitude) : 0;
				_height_map.height(x, y) = height;
			}
		}
		return true;
	}

	/* It is regular iteration round.
	 * Interpolate height values at odd x, even y tiles */
	for (y = 0; y <= _height_map.size_y; y += 2 * step) {
		for (x = 0; x < _height_map.size_x; x += 2 * step) {
			height_t h00 = _height_map.height(x + 0 * step, y);
			height_t h02 = _height_map.height(x + 2 * step, y);
			height_t h01 = (h00 + h02) / 2;
			_height_map.height(x + 1 * step, y) = h01;
		}
	}

	/* Interpolate height values at odd y tiles */
	for (y = 0; y < _height_map.size_y; y += 2 * step) {
		for (x = 0; x <= _height_map.size_x; x += step) {
			height_t h00 = _height_map.height(x, y + 0 * step);
			height_t h20 = _height_map.height(x, y + 2 * step);
			height_t h10 = (h00 + h20) / 2;
			_height_map.height(x, y + 1 * step) = h10;
		}
	}

	/* Add noise for next higher frequency (smaller steps) */
	for (y = 0; y <= _height_map.size_y; y += step) {
		for (x = 0; x <= _height_map.size_x; x += step) {
			_height_map.height(x, y) += RandomHeight(amplitude);
		}
	}

	return (step > 1);
}