2001-05-24 19:22:35 +00:00
|
|
|
/*
|
|
|
|
noisetextures.c
|
|
|
|
|
|
|
|
Noise texture generators
|
|
|
|
|
|
|
|
noise_plasma
|
|
|
|
Copyright (C) 2001 Ragnvald `Despair` Maartmann-Moe IV.
|
|
|
|
|
|
|
|
noise_diamondsquare (originally fractalnoise)
|
|
|
|
Copyright (C) 2000 Forest `LordHavoc` Hale.
|
|
|
|
|
|
|
|
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 2
|
|
|
|
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, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
2003-01-15 15:31:36 +00:00
|
|
|
|
|
|
|
static __attribute__ ((unused)) const char rcsid[] =
|
|
|
|
"$Id$";
|
|
|
|
|
2001-05-24 19:22:35 +00:00
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
2001-09-01 08:57:04 +00:00
|
|
|
|
2001-05-24 19:22:35 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "QF/mathlib.h"
|
2001-10-06 00:39:22 +00:00
|
|
|
#include "QF/sys.h"
|
2003-01-06 18:28:13 +00:00
|
|
|
#include "QF/GL/qf_noisetextures.h"
|
2001-10-06 00:39:22 +00:00
|
|
|
|
|
|
|
#include "compat.h"
|
2001-05-24 19:22:35 +00:00
|
|
|
|
2001-08-22 11:00:25 +00:00
|
|
|
|
2001-05-24 19:22:35 +00:00
|
|
|
void
|
2001-10-06 00:39:22 +00:00
|
|
|
noise_diamondsquare (unsigned char *noise, unsigned int size,
|
|
|
|
unsigned int startgrid)
|
2001-05-24 19:22:35 +00:00
|
|
|
{
|
2001-10-06 00:39:22 +00:00
|
|
|
int amplitude, max, min;
|
|
|
|
int size1 = size - 1;
|
2001-05-24 19:22:35 +00:00
|
|
|
int *noisebuf;
|
2001-10-06 00:39:22 +00:00
|
|
|
unsigned int gridpower, sizepower, g, g2, x, y;
|
2001-05-24 19:22:35 +00:00
|
|
|
|
2002-05-28 05:34:06 +00:00
|
|
|
#define n(x, y) noisebuf[(((y) & size1) << sizepower) + ((x) & size1)]
|
2001-10-06 00:39:22 +00:00
|
|
|
|
2001-11-20 06:57:31 +00:00
|
|
|
for (sizepower = 0; (1 << sizepower) < size; sizepower++);
|
2001-10-06 00:39:22 +00:00
|
|
|
if (size != (1 << sizepower))
|
2002-05-14 06:12:29 +00:00
|
|
|
Sys_Error("fractalnoise: size must be power of 2");
|
2001-10-06 00:39:22 +00:00
|
|
|
|
2001-11-20 06:57:31 +00:00
|
|
|
for (gridpower = 0; (1 << gridpower) < startgrid; gridpower++);
|
2001-10-06 00:39:22 +00:00
|
|
|
if (startgrid != (1 << gridpower))
|
2002-05-14 06:12:29 +00:00
|
|
|
Sys_Error("fractalnoise: grid must be power of 2");
|
2001-10-06 00:39:22 +00:00
|
|
|
|
|
|
|
startgrid = bound(0, startgrid, size);
|
|
|
|
amplitude = 0xFFFF; // this gets halved before use
|
2001-05-24 19:22:35 +00:00
|
|
|
noisebuf = calloc (size * size, sizeof (int));
|
2001-10-06 00:39:22 +00:00
|
|
|
memset(noisebuf, 0, size * size * sizeof(int));
|
2001-05-24 19:22:35 +00:00
|
|
|
|
2001-10-06 00:39:22 +00:00
|
|
|
for (g2 = startgrid; g2; g2 >>= 1) {
|
|
|
|
// Brownian Motion
|
|
|
|
amplitude >>= 1;
|
2001-05-24 19:22:35 +00:00
|
|
|
for (y = 0; y < size; y += g2)
|
|
|
|
for (x = 0; x < size; x += g2)
|
2001-10-06 00:39:22 +00:00
|
|
|
n (x,y) += (rand () & amplitude);
|
|
|
|
|
|
|
|
g = g2 >> 1;
|
|
|
|
if (g) {
|
|
|
|
// subdivide, diamond-square algorithm
|
|
|
|
// diamond
|
|
|
|
for (y = 0; y < size; y += g2)
|
|
|
|
for (x = 0; x < size; x += g2)
|
|
|
|
n (x + g, y + g) =
|
|
|
|
(n (x, y) + n (x + g2, y) + n (x, y + g2) +
|
|
|
|
n (x + g2, y + g2)) >> 2;
|
|
|
|
// square
|
|
|
|
for (y = 0; y < size; y += g2)
|
|
|
|
for (x = 0; x < size; x += g2) {
|
|
|
|
n (x + g, y) = (n (x, y) + n (x + g2, y) +
|
|
|
|
n (x + g, y - g) + n (x + g, y + g)) >> 2;
|
|
|
|
n (x, y + g) = (n (x, y) + n (x, y + g2) +
|
|
|
|
n (x - g, y + g) + n (x + g, y + g)) >> 2;
|
2001-05-24 19:22:35 +00:00
|
|
|
}
|
2001-10-06 00:39:22 +00:00
|
|
|
}
|
2001-05-24 19:22:35 +00:00
|
|
|
}
|
|
|
|
// find range of noise values
|
|
|
|
min = max = 0;
|
|
|
|
for (y = 0; y < size; y++)
|
|
|
|
for (x = 0; x < size; x++) {
|
|
|
|
if (n (x, y) < min)
|
|
|
|
min = n (x, y);
|
|
|
|
if (n (x, y) > max)
|
|
|
|
max = n (x, y);
|
|
|
|
}
|
|
|
|
max -= min;
|
2001-10-06 00:39:22 +00:00
|
|
|
max++;
|
2001-05-24 19:22:35 +00:00
|
|
|
// normalize noise and copy to output
|
|
|
|
for (y = 0; y < size; y++)
|
|
|
|
for (x = 0; x < size; x++)
|
2001-10-06 00:39:22 +00:00
|
|
|
*noise++ = (unsigned char) (((n (x, y) - min) * 256) / max);
|
2001-05-24 19:22:35 +00:00
|
|
|
free (noisebuf);
|
|
|
|
#undef n
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
noise_plasma (unsigned char *noise, int size)
|
|
|
|
{
|
2001-10-06 00:39:22 +00:00
|
|
|
unsigned int a, b, c, d, i, j, k;
|
2001-05-24 19:22:35 +00:00
|
|
|
|
|
|
|
if (128 >= size)
|
|
|
|
d = 64 / size;
|
|
|
|
else
|
|
|
|
d = -size / 64;
|
|
|
|
|
|
|
|
memset(noise, 128, sizeof (*noise));
|
|
|
|
|
2001-09-05 06:20:45 +00:00
|
|
|
for (i = size; i > 0; i /= 2) {
|
|
|
|
for (j=0; j < size; j += i) {
|
|
|
|
for (k=0; k < size; k += i) {
|
|
|
|
if (d >= 0)
|
2001-05-24 19:22:35 +00:00
|
|
|
c = i * d;
|
|
|
|
else
|
|
|
|
c = -i / d;
|
|
|
|
|
2001-09-05 06:20:45 +00:00
|
|
|
c = qfrandom (c * 2) - c;
|
2001-05-24 19:22:35 +00:00
|
|
|
|
2001-09-05 06:20:45 +00:00
|
|
|
for (a=j; a < j + i; a++)
|
|
|
|
for (b = k; b < k + i; b++)
|
|
|
|
noise[a * size + b] += c;
|
2001-05-24 19:22:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|