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