Blame operations/common/perlin/perlin.c

Packit Service 2781ba
/* Coherent noise function over 1, 2 or 3 dimensions */
Packit Service 2781ba
/* (copyright Ken Perlin) */
Packit Service 2781ba
Packit Service 2781ba
#include "config.h"
Packit Service 2781ba
#include <stdlib.h>
Packit Service 2781ba
#include <stdio.h>
Packit Service 2781ba
#include <math.h>
Packit Service 2781ba
#include "perlin.h"
Packit Service 2781ba
Packit Service 2781ba
/* random is not portable to all platforms */
Packit Service 2781ba
#define random g_random_int
Packit Service 2781ba
Packit Service 2781ba
static int p[B + B + 2];
Packit Service 2781ba
static double g3[B + B + 2][3];
Packit Service 2781ba
static double g2[B + B + 2][2];
Packit Service 2781ba
static double g1[B + B + 2];
Packit Service 2781ba
static int start = 1;
Packit Service 2781ba
Packit Service 2781ba
double
Packit Service 2781ba
noise1 (double arg)
Packit Service 2781ba
{
Packit Service 2781ba
  int       bx0, bx1;
Packit Service 2781ba
  double    rx0, rx1, sx, t, u, v, vec[1];
Packit Service 2781ba
Packit Service 2781ba
  vec[0] = arg;
Packit Service 2781ba
  if (start)
Packit Service 2781ba
    {
Packit Service 2781ba
      start = 0;
Packit Service 2781ba
      perlin_init ();
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  setup (0, bx0, bx1, rx0, rx1);
Packit Service 2781ba
Packit Service 2781ba
  sx = s_curve (rx0);
Packit Service 2781ba
  u = rx0 * g1[p[bx0]];
Packit Service 2781ba
  v = rx1 * g1[p[bx1]];
Packit Service 2781ba
Packit Service 2781ba
  return (lerp (sx, u, v));
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
double
Packit Service 2781ba
noise2 (double vec[2])
Packit Service 2781ba
{
Packit Service 2781ba
  int       bx0, bx1, by0, by1, b00, b10, b01, b11;
Packit Service 2781ba
  double    rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
Packit Service 2781ba
  int       i, j;
Packit Service 2781ba
Packit Service 2781ba
  if (start)
Packit Service 2781ba
    {
Packit Service 2781ba
      start = 0;
Packit Service 2781ba
      perlin_init ();
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  setup (0, bx0, bx1, rx0, rx1);
Packit Service 2781ba
  setup (1, by0, by1, ry0, ry1);
Packit Service 2781ba
Packit Service 2781ba
  i = p[bx0];
Packit Service 2781ba
  j = p[bx1];
Packit Service 2781ba
Packit Service 2781ba
  b00 = p[i + by0];
Packit Service 2781ba
  b10 = p[j + by0];
Packit Service 2781ba
  b01 = p[i + by1];
Packit Service 2781ba
  b11 = p[j + by1];
Packit Service 2781ba
Packit Service 2781ba
  sx = s_curve (rx0);
Packit Service 2781ba
  sy = s_curve (ry0);
Packit Service 2781ba
Packit Service 2781ba
  q = g2[b00];
Packit Service 2781ba
  u = at2 (rx0, ry0);
Packit Service 2781ba
  q = g2[b10];
Packit Service 2781ba
  v = at2 (rx1, ry0);
Packit Service 2781ba
  a = lerp (sx, u, v);
Packit Service 2781ba
Packit Service 2781ba
  q = g2[b01];
Packit Service 2781ba
  u = at2 (rx0, ry1);
Packit Service 2781ba
  q = g2[b11];
Packit Service 2781ba
  v = at2 (rx1, ry1);
Packit Service 2781ba
  b = lerp (sx, u, v);
Packit Service 2781ba
Packit Service 2781ba
  return lerp (sy, a, b);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
double
Packit Service 2781ba
noise3 (double vec[3])
Packit Service 2781ba
{
Packit Service 2781ba
  int       bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
Packit Service 2781ba
  double    rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
Packit Service 2781ba
  int       i, j;
Packit Service 2781ba
Packit Service 2781ba
  if (start)
Packit Service 2781ba
    {
Packit Service 2781ba
      start = 0;
Packit Service 2781ba
      perlin_init ();
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  setup (0, bx0, bx1, rx0, rx1);
Packit Service 2781ba
  setup (1, by0, by1, ry0, ry1);
Packit Service 2781ba
  setup (2, bz0, bz1, rz0, rz1);
Packit Service 2781ba
Packit Service 2781ba
  i = p[bx0];
Packit Service 2781ba
  j = p[bx1];
Packit Service 2781ba
Packit Service 2781ba
  b00 = p[i + by0];
Packit Service 2781ba
  b10 = p[j + by0];
Packit Service 2781ba
  b01 = p[i + by1];
Packit Service 2781ba
  b11 = p[j + by1];
Packit Service 2781ba
Packit Service 2781ba
  t = s_curve (rx0);
Packit Service 2781ba
  sy = s_curve (ry0);
Packit Service 2781ba
  sz = s_curve (rz0);
Packit Service 2781ba
Packit Service 2781ba
  q = g3[b00 + bz0];
Packit Service 2781ba
  u = at3 (rx0, ry0, rz0);
Packit Service 2781ba
  q = g3[b10 + bz0];
Packit Service 2781ba
  v = at3 (rx1, ry0, rz0);
Packit Service 2781ba
  a = lerp (t, u, v);
Packit Service 2781ba
Packit Service 2781ba
  q = g3[b01 + bz0];
Packit Service 2781ba
  u = at3 (rx0, ry1, rz0);
Packit Service 2781ba
  q = g3[b11 + bz0];
Packit Service 2781ba
  v = at3 (rx1, ry1, rz0);
Packit Service 2781ba
  b = lerp (t, u, v);
Packit Service 2781ba
Packit Service 2781ba
  c = lerp (sy, a, b);
Packit Service 2781ba
Packit Service 2781ba
  q = g3[b00 + bz1];
Packit Service 2781ba
  u = at3 (rx0, ry0, rz1);
Packit Service 2781ba
  q = g3[b10 + bz1];
Packit Service 2781ba
  v = at3 (rx1, ry0, rz1);
Packit Service 2781ba
  a = lerp (t, u, v);
Packit Service 2781ba
Packit Service 2781ba
  q = g3[b01 + bz1];
Packit Service 2781ba
  u = at3 (rx0, ry1, rz1);
Packit Service 2781ba
  q = g3[b11 + bz1];
Packit Service 2781ba
  v = at3 (rx1, ry1, rz1);
Packit Service 2781ba
  b = lerp (t, u, v);
Packit Service 2781ba
Packit Service 2781ba
  d = lerp (sy, a, b);
Packit Service 2781ba
Packit Service 2781ba
  return lerp (sz, c, d);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
normalize2 (double v[2])
Packit Service 2781ba
{
Packit Service 2781ba
  double    s;
Packit Service 2781ba
Packit Service 2781ba
  s = sqrt (v[0] * v[0] + v[1] * v[1]);
Packit Service 2781ba
  v[0] = v[0] / s;
Packit Service 2781ba
  v[1] = v[1] / s;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
normalize3 (double v[3])
Packit Service 2781ba
{
Packit Service 2781ba
  double    s;
Packit Service 2781ba
Packit Service 2781ba
  s = sqrt (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
Packit Service 2781ba
  v[0] = v[0] / s;
Packit Service 2781ba
  v[1] = v[1] / s;
Packit Service 2781ba
  v[2] = v[2] / s;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
perlin_init (void)
Packit Service 2781ba
{
Packit Service 2781ba
  int       i, j, k;
Packit Service 2781ba
Packit Service 2781ba
  for (i = 0; i < B; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      p[i] = i;
Packit Service 2781ba
      g1[i] = (double) ((random () % (B + B)) - B) / B;
Packit Service 2781ba
Packit Service 2781ba
      for (j = 0; j < 2; j++)
Packit Service 2781ba
        g2[i][j] = (double) ((random () % (B + B)) - B) / B;
Packit Service 2781ba
      normalize2 (g2[i]);
Packit Service 2781ba
Packit Service 2781ba
      for (j = 0; j < 3; j++)
Packit Service 2781ba
        g3[i][j] = (double) ((random () % (B + B)) - B) / B;
Packit Service 2781ba
      normalize3 (g3[i]);
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  while (--i)
Packit Service 2781ba
    {
Packit Service 2781ba
      k = p[i];
Packit Service 2781ba
      p[i] = p[j = random () % B];
Packit Service 2781ba
      p[j] = k;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  for (i = 0; i < B + 2; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      p[B + i] = p[i];
Packit Service 2781ba
      g1[B + i] = g1[i];
Packit Service 2781ba
      for (j = 0; j < 2; j++)
Packit Service 2781ba
        g2[B + i][j] = g2[i][j];
Packit Service 2781ba
      for (j = 0; j < 3; j++)
Packit Service 2781ba
        g3[B + i][j] = g3[i][j];
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
/* --- My harmonic summing functions - PDB --------------------------*/
Packit Service 2781ba
Packit Service 2781ba
/*
Packit Service 2781ba
   In what follows "alpha" is the weight when the sum is formed.
Packit Service 2781ba
   Typically it is 2, As this approaches 1 the function is noisier.
Packit Service 2781ba
   "beta" is the harmonic scaling/spacing, typically 2.
Packit Service 2781ba
*/
Packit Service 2781ba
Packit Service 2781ba
double
Packit Service 2781ba
PerlinNoise1D (double x, double alpha, double beta, int n)
Packit Service 2781ba
{
Packit Service 2781ba
  int       i;
Packit Service 2781ba
  double    val, sum = 0;
Packit Service 2781ba
  double    p, scale = 1;
Packit Service 2781ba
Packit Service 2781ba
  p = x;
Packit Service 2781ba
  for (i = 0; i < n; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      val = noise1 (p);
Packit Service 2781ba
      sum += val / scale;
Packit Service 2781ba
      scale *= alpha;
Packit Service 2781ba
      p *= beta;
Packit Service 2781ba
    }
Packit Service 2781ba
  return (sum);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
double
Packit Service 2781ba
PerlinNoise2D (double x, double y, double alpha, double beta, int n)
Packit Service 2781ba
{
Packit Service 2781ba
  int       i;
Packit Service 2781ba
  double    val, sum = 0;
Packit Service 2781ba
  double    p[2], scale = 1;
Packit Service 2781ba
Packit Service 2781ba
  p[0] = x;
Packit Service 2781ba
  p[1] = y;
Packit Service 2781ba
  for (i = 0; i < n; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      val = noise2 (p);
Packit Service 2781ba
      sum += val / scale;
Packit Service 2781ba
      scale *= alpha;
Packit Service 2781ba
      p[0] *= beta;
Packit Service 2781ba
      p[1] *= beta;
Packit Service 2781ba
    }
Packit Service 2781ba
  return (sum);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
double
Packit Service 2781ba
PerlinNoise3D (double x, double y, double z, double alpha, double beta, int n)
Packit Service 2781ba
{
Packit Service 2781ba
  int       i;
Packit Service 2781ba
  double    val, sum = 0;
Packit Service 2781ba
  double    p[3], scale = 1.0;
Packit Service 2781ba
Packit Service 2781ba
  if (z < 0.0000)
Packit Service 2781ba
    return PerlinNoise2D (x, y, alpha, beta, n);
Packit Service 2781ba
  p[0] = x;
Packit Service 2781ba
  p[1] = y;
Packit Service 2781ba
  p[2] = z;
Packit Service 2781ba
Packit Service 2781ba
  for (i = 0; i < n; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      val = noise3 (p);
Packit Service 2781ba
      sum += val / scale;
Packit Service 2781ba
      scale *= alpha;
Packit Service 2781ba
      p[0] *= beta;
Packit Service 2781ba
      p[1] *= beta;
Packit Service 2781ba
      p[2] *= beta;
Packit Service 2781ba
    }
Packit Service 2781ba
  return (sum);
Packit Service 2781ba
}