/*
*
* LiveWallpaper
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Copyright (C) 2012-2016 Maximilian Schnarr
*
*
* All simplex noise functions were taken from Stefan Gustavson. You can find
* the original code here:
* http://webstaff.itn.liu.se/~stegu/simplexnoise/SimplexNoise.java
* The original code was placed in the public domain, so all lw_simplex_noise_*
* functions are also placed in the public domain.
*
* You can find a good description of the simplex noise algorithm here:
* http://webstaff.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
*/
/**
* SECTION: noise
* @Short_description: Functions generating noise
* @Title: Noise
*
* These functions may help you to add some randomness to your live wallpapers.
*/
#include
#include
/* Permutation and gradient table */
#define PERM_SIZE 256
static int perm[2 * PERM_SIZE];
static float grad[PERM_SIZE][2];
/* Skewing and unskewing factors */
#define F2 0.36602540f
#define G2 0.21132486f
/**
* lw_noise_init:
*
* Initializes internal tables used by the simplex noise algorithm. Make sure to
* call this before using the lw_simplex_noise_2f() function. The tables will only
* be generated once so calling this multiple times has no effect.
*
* Since: 0.4
*/
void
lw_noise_init()
{
static gboolean is_initialized = FALSE;
if(!is_initialized)
{
int i;
/* Create permutation table */
for(i = 0; i < PERM_SIZE; i++)
{
perm[i] = i;
}
/* Make the permutation table random */
for(i = 0; i < PERM_SIZE; i++)
{
int tmp = perm[i];
int j = rand() % PERM_SIZE;
perm[i] = perm[j];
perm[j] = tmp;
}
/* Double the permutation table to remove the need for index wrapping */
for(i = PERM_SIZE; i < 2 * PERM_SIZE; i++)
{
perm[i] = perm[i - PERM_SIZE];
}
/* Generate random gradient table */
for(i = 0; i < PERM_SIZE; i++)
{
grad[i][0] = rand2f(-1.0f, 1.0f);
grad[i][1] = rand2f(-1.0f, 1.0f);
}
is_initialized = TRUE;
}
}
/**
* lw_simplex_noise_2f:
* @x: A x coordinate
* @y: A y coordinate
*
* Calculates a noise value at the position x, y using the simplex noise algorithm.
*
*
* This function cannot handle negative coordinates, so make sure that @x >= 0 and @y >= 0.
*
*
* Returns: A noise value in the interval [-1;1]
*
* Since: 0.4
*/
float
lw_simplex_noise_2f(float x, float y)
{
float t;
/* Noise contributions from the three corners */
float n0, n1, n2;
/* The distances from the cell origin in (x,y) unskewed coords */
float x0, y0, x1, y1, x2, y2;
/* x and y skewed to (i,j) coords */
int i, j;
/* Offsets for second (middle) corner of simplex in (i,j) coords */
int i1, j1;
/* Permutation/Gradient table indices */
int pi, pj, gi0, gi1, gi2;
/* Skew the input space to determine which simplex cell we're in */
t = (x + y) * F2;
i = floor(x + t);
j = floor(y + t);
/* Unskew the cell origin back to (x, y) space */
t = (i + j) * G2;
/* X0 = i - t; Y0 = j - t; */
x0 = x - i + t; /* x - X0 */
y0 = y - j + t; /* y - Y0 */
/* For the 2D case, the simplex shape is an equilateral triangle.
* Determine which simplex we are in. */
if(x0 > y0)
{
/* lower triangle, XY order: (0,0)->(1,0)->(1,1) */
i1 = 1;
j1 = 0;
}
else
{
/* upper triangle, YX order: (0,0)->(0,1)->(1,1) */
i1 = 0;
j1 = 1;
}
/* A step of (1,0) in (i,j) means a step of (1-G2,-G2) in (x,y) and
* a step of (0,1) in (i,j) means a step of (-G2,1-G2) in (x,y). */
x1 = x0 - i1 + G2;
y1 = y0 - j1 + G2;
x2 = x0 - 1.0 + 2.0 * G2;
y2 = y0 - 1.0 + 2.0 * G2;
/* Work out the hashed gradient indices of the three simplex corners */
pi = i % PERM_SIZE;
pj = j % PERM_SIZE;
gi0 = perm[pi + perm[pj]];
gi1 = perm[pi + i1 + perm[pj + j1]];
gi2 = perm[pi + 1 + perm[pj + 1 ]];
/* Calculate the contribution from the three corners */
t = 0.5 - x0*x0 - y0*y0;
if(t < 0) n0 = 0.0f;
else
{
t *= t;
n0 = t * t * (grad[gi0][0] * x0 + grad[gi0][1] * y0);
}
t = 0.5 - x1*x1 - y1*y1;
if(t < 0) n1 = 0.0f;
else
{
t *= t;
n1 = t * t * (grad[gi1][0] * x1 + grad[gi1][1] * y1);
}
t = 0.5 - x2*x2 - y2*y2;
if(t < 0) n2 = 0.0f;
else
{
t *= t;
n2 = t * t * (grad[gi2][0] * x2 + grad[gi2][1] * y2);
}
/* Add contributions from each corner to get the final noise value.
* The result is scaled to return values in the interval [-1;1]. */
return 70.0f * (n0 + n1 + n2);
}