Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trandom.h"
Toshihiro Shimizu 890ddd
//#include "tfxparam.h"
Toshihiro Shimizu 890ddd
#include "perlinnoise.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//using std::cout;
Toshihiro Shimizu 890ddd
//using std::endl;
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double PerlinNoise::LinearNoise(double x, double y, double t)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int ix, iy, it, ix1, iy1, it1;
Toshihiro Shimizu 890ddd
	double dx, dy, dt, val1, val2, val3, val4, val5, val6;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ix = (int)x;
Toshihiro Shimizu 890ddd
	iy = (int)y;
Toshihiro Shimizu 890ddd
	it = (int)t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	dx = x - ix;
Toshihiro Shimizu 890ddd
	dy = y - iy;
Toshihiro Shimizu 890ddd
	dt = t - it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ix = ix % Size;
Toshihiro Shimizu 890ddd
	iy = iy % Size;
Toshihiro Shimizu 890ddd
	it = it % TimeSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ix1 = (ix + 1) % Size;
Toshihiro Shimizu 890ddd
	iy1 = (iy + 1) % Size;
Toshihiro Shimizu 890ddd
	it1 = (it + 1) % TimeSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	val1 = Noise[it + TimeSize * iy + TimeSize * Size * ix] +
Toshihiro Shimizu 890ddd
		   dx * (Noise[it + TimeSize * iy + TimeSize * Size * ix1] -
Toshihiro Shimizu 890ddd
				 Noise[it + TimeSize * iy + TimeSize * Size * ix]);
Toshihiro Shimizu 890ddd
	val2 = Noise[it + TimeSize * iy1 + TimeSize * Size * ix] +
Toshihiro Shimizu 890ddd
		   dx * (Noise[it + TimeSize * iy1 + TimeSize * Size * ix1] -
Toshihiro Shimizu 890ddd
				 Noise[it + TimeSize * iy1 + TimeSize * Size * ix]);
Toshihiro Shimizu 890ddd
	val3 = Noise[it1 + TimeSize * iy + TimeSize * Size * ix] +
Toshihiro Shimizu 890ddd
		   dx * (Noise[it1 + TimeSize * iy + TimeSize * Size * ix1] -
Toshihiro Shimizu 890ddd
				 Noise[it1 + TimeSize * iy + TimeSize * Size * ix]);
Toshihiro Shimizu 890ddd
	val4 = Noise[it1 + TimeSize * iy1 + TimeSize * Size * ix] +
Toshihiro Shimizu 890ddd
		   dx * (Noise[it1 + TimeSize * iy1 + TimeSize * Size * ix1] -
Toshihiro Shimizu 890ddd
				 Noise[it1 + TimeSize * iy1 + TimeSize * Size * ix]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	val5 = (val1 + dy * (val2 - val1));
Toshihiro Shimizu 890ddd
	val6 = (val3 + dy * (val4 - val3));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (val5 + dt * (val6 - val5));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double PerlinNoise::Turbolence(double u, double v, double k, double grain)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	u += Offset;
Toshihiro Shimizu 890ddd
	v += Offset;
Toshihiro Shimizu 890ddd
	Pixel_size = 0.05;
Toshihiro Shimizu 890ddd
	double t = 0.0, scale = 1.0, tscale = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	u /= grain;
Toshihiro Shimizu 890ddd
	v /= grain;
Toshihiro Shimizu 890ddd
	k /= 10;
Toshihiro Shimizu 890ddd
	while (scale > Pixel_size) {
Toshihiro Shimizu 890ddd
		tscale += scale;
Toshihiro Shimizu 890ddd
		t += LinearNoise(u / scale, v / scale, k / scale) * scale;
Toshihiro Shimizu 890ddd
		scale /= 2.0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return t / tscale;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double PerlinNoise::Turbolence(double u, double v, double k, double grain, double min, double max)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	u += Offset;
Toshihiro Shimizu 890ddd
	v += Offset;
Toshihiro Shimizu 890ddd
	Pixel_size = 0.05;
Toshihiro Shimizu 890ddd
	double t = 0.0, scale = 1.0, tscale = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	u /= grain;
Toshihiro Shimizu 890ddd
	v /= grain;
Toshihiro Shimizu 890ddd
	k /= 10;
Toshihiro Shimizu 890ddd
	while (scale > Pixel_size) {
Toshihiro Shimizu 890ddd
		tscale += scale;
Toshihiro Shimizu 890ddd
		t += LinearNoise(u / scale, v / scale, k / scale) * scale;
Toshihiro Shimizu 890ddd
		scale /= 2.0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	t = t / tscale;
Toshihiro Shimizu 890ddd
	if (t < min)
Toshihiro Shimizu 890ddd
		t = 0;
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		if (t > max)
Toshihiro Shimizu 890ddd
			t = 1;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			t = (t - min) / ((max - min));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double PerlinNoise::Marble(double u, double v, double k, double grain)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	u += Offset;
Toshihiro Shimizu 890ddd
	v += Offset;
Toshihiro Shimizu 890ddd
	Pixel_size = 0.05;
Toshihiro Shimizu 890ddd
	double t = 0.0, scale = 1.0, tscale = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	u /= grain;
Toshihiro Shimizu 890ddd
	v /= grain;
Toshihiro Shimizu 890ddd
	k /= 10;
Toshihiro Shimizu 890ddd
	while (scale > Pixel_size) {
Toshihiro Shimizu 890ddd
		tscale += scale;
Toshihiro Shimizu 890ddd
		t += LinearNoise(u / scale, v / scale, k / scale) * scale;
Toshihiro Shimizu 890ddd
		scale /= 2.0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	t = 10 * t;
Toshihiro Shimizu 890ddd
	return (t - (int)t);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double PerlinNoise::Marble(double u, double v, double k, double grain, double min, double max)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	u += Offset;
Toshihiro Shimizu 890ddd
	v += Offset;
Toshihiro Shimizu 890ddd
	Pixel_size = 0.05;
Toshihiro Shimizu 890ddd
	double t = 0.0, scale = 1.0, tscale = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	u /= grain;
Toshihiro Shimizu 890ddd
	v /= grain;
Toshihiro Shimizu 890ddd
	k /= 10;
Toshihiro Shimizu 890ddd
	while (scale > Pixel_size) {
Toshihiro Shimizu 890ddd
		tscale += scale;
Toshihiro Shimizu 890ddd
		t += LinearNoise(u / scale, v / scale, k / scale) * scale;
Toshihiro Shimizu 890ddd
		scale /= 2.0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	t = 10 * t;
Toshihiro Shimizu 890ddd
	t = (t - (int)t);
Toshihiro Shimizu 890ddd
	if (t < min)
Toshihiro Shimizu 890ddd
		t = 0;
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		if (t > max)
Toshihiro Shimizu 890ddd
			t = 1;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			t = (t - min) / ((max - min));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PerlinNoise::PerlinNoise()
Shinya Kitaoka 42bfb6
	: Noise(new float[Size * Size * TimeSize])
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRandom random(1);
Toshihiro Shimizu 890ddd
	for (int i = 0; i < Size; i++) {
Toshihiro Shimizu 890ddd
		for (int j = 0; j < Size; j++) {
Toshihiro Shimizu 890ddd
			for (int k = 0; k < TimeSize; k++) {
Toshihiro Shimizu 890ddd
				float tmp = random.getFloat();
Toshihiro Shimizu 890ddd
				//cout << "tmp = " << tmp << "HM = "<< HowMany<< endl;
Toshihiro Shimizu 890ddd
				Noise[k + TimeSize * j + TimeSize * Size * i] = tmp;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//cout << "HowMany = " << HowMany <
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int PerlinNoise::Size = 60;
Toshihiro Shimizu 890ddd
int PerlinNoise::TimeSize = 20;
Toshihiro Shimizu 890ddd
int PerlinNoise::Offset = 1000000;
Toshihiro Shimizu 890ddd
double PerlinNoise::Pixel_size = 0.01; //il pixel size va animato da 1 (escluso)
Toshihiro Shimizu 890ddd
									   //a 0.1 (consigliato) fino ad un min di 0.001
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
template <typename pixel=""></typename>
Toshihiro Shimizu 890ddd
void doCloudsT(const TRasterPT<pixel> &ras, const TSpectrumT<pixel> &spectrum,</pixel></pixel>
Toshihiro Shimizu 890ddd
			   TPointD &tilepos, double evolution, double size, double min, double max, int type, double scale)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int j;
Toshihiro Shimizu 890ddd
	TAffine aff = TScale(1 / scale);
Toshihiro Shimizu 890ddd
	PerlinNoise Noise;
Toshihiro Shimizu 890ddd
	ras->lock();
Toshihiro Shimizu 890ddd
	if (type == PNOISE_CLOUDS) {
Toshihiro Shimizu 890ddd
		for (j = 0; j < ras->getLy(); j++) {
Toshihiro Shimizu 890ddd
			TPointD pos = tilepos;
Toshihiro Shimizu 890ddd
			pos.y += j;
Toshihiro Shimizu 890ddd
			PIXEL *pix = ras->pixels(j);
Toshihiro Shimizu 890ddd
			PIXEL *endPix = pix + ras->getLx();
Toshihiro Shimizu 890ddd
			while (pix < endPix) {
Toshihiro Shimizu 890ddd
				TPointD posAff = aff * pos;
Toshihiro Shimizu 890ddd
				double pnoise = Noise.Turbolence(posAff.x, posAff.y, evolution, size, min, max);
Toshihiro Shimizu 890ddd
				pos.x += 1.0;
Toshihiro Shimizu 890ddd
				*pix++ = spectrum.getPremultipliedValue(pnoise);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		for (j = 0; j < ras->getLy(); j++) {
Toshihiro Shimizu 890ddd
			TPointD pos = tilepos;
Toshihiro Shimizu 890ddd
			pos.y += j;
Toshihiro Shimizu 890ddd
			PIXEL *pix = ras->pixels(j);
Toshihiro Shimizu 890ddd
			PIXEL *endPix = pix + ras->getLx();
Toshihiro Shimizu 890ddd
			while (pix < endPix) {
Toshihiro Shimizu 890ddd
				TPointD posAff = aff * pos;
Toshihiro Shimizu 890ddd
				double pnoise = Noise.Marble(posAff.x, posAff.y, evolution, size, min, max);
Toshihiro Shimizu 890ddd
				pos.x += 1.0;
Toshihiro Shimizu 890ddd
				*pix++ = spectrum.getPremultipliedValue(pnoise);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void doClouds(
Toshihiro Shimizu 890ddd
	const TRasterP &ras,
Toshihiro Shimizu 890ddd
	const TSpectrumParamP colors,
Toshihiro Shimizu 890ddd
	TPointD pos,
Toshihiro Shimizu 890ddd
	double evolution,
Toshihiro Shimizu 890ddd
	double size,
Toshihiro Shimizu 890ddd
	double min,
Toshihiro Shimizu 890ddd
	double max,
Toshihiro Shimizu 890ddd
	int type,
Toshihiro Shimizu 890ddd
	double scale,
Toshihiro Shimizu 890ddd
	double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((TRaster32P)ras)
Toshihiro Shimizu 890ddd
		doCloudsT<tpixel32>(</tpixel32>
Toshihiro Shimizu 890ddd
			ras,
Toshihiro Shimizu 890ddd
			colors->getValue(frame),
Toshihiro Shimizu 890ddd
			pos, evolution, size, min, max, type, scale);
Toshihiro Shimizu 890ddd
	else if ((TRaster64P)ras)
Toshihiro Shimizu 890ddd
		doCloudsT<tpixel64>(</tpixel64>
Toshihiro Shimizu 890ddd
			ras,
Toshihiro Shimizu 890ddd
			colors->getValue64(frame),
Toshihiro Shimizu 890ddd
			pos, evolution, size, min, max, type, scale);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		throw TException("CloudsFx: unsupported Pixel Type");
Toshihiro Shimizu 890ddd
}