Merge branch 'Cubitect:master' into master

This commit is contained in:
KaiSandstrom 2023-01-15 11:30:53 -05:00 committed by GitHub
commit c9fc194cde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 131 additions and 115 deletions

166
finders.c
View File

@ -4409,8 +4409,8 @@ int getParaRange(const DoublePerlinNoise *para, double *pmin, double *pmax,
int maxrad, maxiter;
int err = 1;
*pmin = DBL_MAX;
*pmax = -DBL_MAX;
if (pmin) *pmin = DBL_MAX;
if (pmax) *pmax = -DBL_MAX;
lmin = DBL_MAX, lmax = 0;
for (i = 0; i < para->octA.octcnt; i++)
@ -4436,8 +4436,8 @@ int getParaRange(const DoublePerlinNoise *para, double *pmin, double *pmax,
if (err)
return err;
}
if (v < *pmin) *pmin = v;
if (v > *pmax) *pmax = v;
if (pmin && v < *pmin) *pmin = v;
if (pmax && v > *pmax) *pmax = v;
}
}
return 0;
@ -4451,14 +4451,20 @@ int getParaRange(const DoublePerlinNoise *para, double *pmin, double *pmax,
{
for (i = 0; i < w; i += step)
{
v = getParaDescent(para, +factor, x, z, w, h, i, j,
step, step, dr, data, func);
if (v != v) goto L_end;
if (v < *pmin) *pmin = v;
v = -getParaDescent(para, -factor, x, z, w, h, i, j,
step, step, dr, data, func);
if (v != v) goto L_end;
if (v > *pmax) *pmax = v;
if (pmin)
{
v = getParaDescent(para, +factor, x, z, w, h, i, j,
step, step, dr, data, func);
if (v != v) goto L_end;
if (v < *pmin) *pmin = v;
}
if (pmax)
{
v = -getParaDescent(para, -factor, x, z, w, h, i, j,
step, step, dr, data, func);
if (v != v) goto L_end;
if (v > *pmax) *pmax = v;
}
}
}
@ -4498,93 +4504,97 @@ int getParaRange(const DoublePerlinNoise *para, double *pmin, double *pmax,
skipsiz = (ww+1) * (hh+1) * sizeof(*skip);
skip = (char*) malloc(skipsiz);
// look for minima
memset(skip, 0, skipsiz);
if (pmin)
{ // look for minima
memset(skip, 0, skipsiz);
for (jj = 0; jj <= hh; jj++)
{
j = jj * step; if (j >= h) j = h-1;
for (ii = 0; ii <= ww; ii++)
for (jj = 0; jj <= hh; jj++)
{
i = ii * step; if (i >= w) i = w-1;
if (skip[jj*ww+ii]) continue;
v = factor * sampleDoublePerlin(para, x+i, 0, z+j);
if (func)
j = jj * step; if (j >= h) j = h-1;
for (ii = 0; ii <= ww; ii++)
{
int e = func(data, x+i, z+j, v);
if (e)
{
err = e;
goto L_end;
}
}
// not looking for maxima yet, but we'll update the bounds anyway
if (v > *pmax) *pmax = v;
i = ii * step; if (i >= w) i = w-1;
if (skip[jj*ww+ii]) continue;
dr = beta * (v - *pmin) / vdif;
if (dr > 1.0)
{ // difference is too large -> mark visinity to be skipped
int a, b, r = (int) dr;
for (b = 0; b < r; b++)
v = factor * sampleDoublePerlin(para, x+i, 0, z+j);
if (func)
{
if (b+jj < 0 || b+jj >= hh) continue;
for (a = -r+1; a < r; a++)
int e = func(data, x+i, z+j, v);
if (e)
{
if (a+ii < 0 || a+ii >= ww) continue;
skip[(b+jj)*ww + (a+ii)] = 1;
err = e;
goto L_end;
}
}
continue;
// not looking for maxima yet, but update the bounds anyway
if (pmax && v > *pmax) *pmax = v;
dr = beta * (v - *pmin) / vdif;
if (dr > 1.0)
{ // difference is too large -> mark visinity to be skipped
int a, b, r = (int) dr;
for (b = 0; b < r; b++)
{
if (b+jj < 0 || b+jj >= hh) continue;
for (a = -r+1; a < r; a++)
{
if (a+ii < 0 || a+ii >= ww) continue;
skip[(b+jj)*ww + (a+ii)] = 1;
}
}
continue;
}
v = getParaDescent(para, +factor, x, z, w, h, i, j,
maxrad, maxiter, dr, data, func);
if (v != v) goto L_end;
if (v < *pmin) *pmin = v;
}
v = getParaDescent(para, +factor, x, z, w, h, i, j,
maxrad, maxiter, dr, data, func);
if (v != v) goto L_end;
if (v < *pmin) *pmin = v;
}
}
// look for maxima
memset(skip, 0, skipsiz);
if (pmax)
{ // look for maxima
memset(skip, 0, skipsiz);
for (jj = 0; jj <= hh; jj++)
{
j = jj * step; if (j >= h) j = h-1;
for (ii = 0; ii <= ww; ii++)
for (jj = 0; jj <= hh; jj++)
{
i = ii * step; if (i >= w) i = w-1;
if (skip[jj*ww+ii]) continue;
v = -factor * sampleDoublePerlin(para, x+i, 0, z+j);
if (func)
j = jj * step; if (j >= h) j = h-1;
for (ii = 0; ii <= ww; ii++)
{
int e = func(data, x+i, z+j, -v);
if (e)
{
err = e;
goto L_end;
}
}
i = ii * step; if (i >= w) i = w-1;
if (skip[jj*ww+ii]) continue;
dr = beta * (v + *pmax) / vdif;
if (dr > 1.0)
{ // difference too large -> mark visinity to be skipped
int a, b, r = (int) dr;
for (b = 0; b < r; b++)
v = -factor * sampleDoublePerlin(para, x+i, 0, z+j);
if (func)
{
if (b+jj < 0 || b+jj >= hh) continue;
for (a = -r+1; a < r; a++)
int e = func(data, x+i, z+j, -v);
if (e)
{
if (a+ii < 0 || a+ii >= ww) continue;
skip[(b+jj)*ww + (a+ii)] = 1;
err = e;
goto L_end;
}
}
continue;
dr = beta * (v + *pmax) / vdif;
if (dr > 1.0)
{ // difference too large -> mark visinity to be skipped
int a, b, r = (int) dr;
for (b = 0; b < r; b++)
{
if (b+jj < 0 || b+jj >= hh) continue;
for (a = -r+1; a < r; a++)
{
if (a+ii < 0 || a+ii >= ww) continue;
skip[(b+jj)*ww + (a+ii)] = 1;
}
}
continue;
}
v = -getParaDescent(para, -factor, x, z, w, h, i, j,
maxrad, maxiter, dr, data, func);
if (v != v) goto L_end;
if (v > *pmax) *pmax = v;
}
v = -getParaDescent(para, -factor, x, z, w, h, i, j,
maxrad, maxiter, dr, data, func);
if (v != v) goto L_end;
if (v > *pmax) *pmax = v;
}
}

View File

@ -623,7 +623,7 @@ double getParaDescent(const DoublePerlinNoise *para, double factor,
* error is returned.
*
* The results are written to pmin and pmax (which would be cast to an integer
* during boime mapping).
* during boime mapping). Nullable, to look for minima and maxima separately.
*/
int getParaRange(const DoublePerlinNoise *para, double *pmin, double *pmax,
int x, int z, int w, int h, void *data, int (*func)(void*,int,int,double));

View File

@ -21,7 +21,7 @@ debug: CFLAGS += -DDEBUG -O0 -ggdb3
debug: libcubiomes
release: CFLAGS += -O3 -g3
release: libcubiomes
native: CFLAGS += -O3 -march=native
native: CFLAGS += -O3 -march=native -ffast-math
native: libcubiomes
ifeq ($(OS),Windows_NT)

65
noise.c
View File

@ -5,11 +5,6 @@
#include <stdio.h>
double maintainPrecision(double x)
{
return x - floor(x / 33554432.0 + 0.5) * 33554432.0;
}
// grad()
/*
static double indexedLerp(int idx, double d1, double d2, double d3)
@ -61,17 +56,18 @@ void perlinInit(PerlinNoise *noise, uint64_t *seed)
noise->amplitude = 1.0;
noise->lacunarity = 1.0;
uint8_t *idx = noise->d;
for (i = 0; i < 256; i++)
{
noise->d[i] = i;
idx[i] = i;
}
for (i = 0; i < 256; i++)
{
int j = nextInt(seed, 256 - i) + i;
uint8_t n = noise->d[i];
noise->d[i] = noise->d[j];
noise->d[j] = n;
noise->d[i + 256] = noise->d[i];
uint8_t n = idx[i];
idx[i] = idx[j];
idx[j] = n;
idx[i + 256] = idx[i];
}
}
@ -85,30 +81,31 @@ void xPerlinInit(PerlinNoise *noise, Xoroshiro *xr)
noise->amplitude = 1.0;
noise->lacunarity = 1.0;
uint8_t *idx = noise->d;
for (i = 0; i < 256; i++)
{
noise->d[i] = i;
idx[i] = i;
}
for (i = 0; i < 256; i++)
{
int j = xNextInt(xr, 256 - i) + i;
uint8_t n = noise->d[i];
noise->d[i] = noise->d[j];
noise->d[j] = n;
noise->d[i + 256] = noise->d[i];
uint8_t n = idx[i];
idx[i] = idx[j];
idx[j] = n;
idx[i + 256] = idx[i];
}
}
double samplePerlin(const PerlinNoise *noise, double d1, double d2, double d3,
double yamp, double ymin)
{
d1 += noise->a;
d2 += noise->b;
d3 += noise->c;
int i1 = (int)d1 - (int)(d1 < 0);
int i2 = (int)d2 - (int)(d2 < 0);
int i3 = (int)d3 - (int)(d3 < 0);
const uint8_t *idx = noise->d;
int i1 = (int) floor(d1);
int i2 = (int) floor(d2);
int i3 = (int) floor(d3);
d1 -= i1;
d2 -= i2;
d3 -= i3;
@ -126,21 +123,22 @@ double samplePerlin(const PerlinNoise *noise, double d1, double d2, double d3,
i2 &= 0xff;
i3 &= 0xff;
int a1 = noise->d[i1] + i2;
int a2 = noise->d[a1] + i3;
int a3 = noise->d[a1+1] + i3;
int b1 = noise->d[i1+1] + i2;
int b2 = noise->d[b1] + i3;
int b3 = noise->d[b1+1] + i3;
int a1 = idx[i1] + i2;
int b1 = idx[i1+1] + i2;
double l1 = indexedLerp(noise->d[a2], d1, d2, d3);
double l2 = indexedLerp(noise->d[b2], d1-1, d2, d3);
double l3 = indexedLerp(noise->d[a3], d1, d2-1, d3);
double l4 = indexedLerp(noise->d[b3], d1-1, d2-1, d3);
double l5 = indexedLerp(noise->d[a2+1], d1, d2, d3-1);
double l6 = indexedLerp(noise->d[b2+1], d1-1, d2, d3-1);
double l7 = indexedLerp(noise->d[a3+1], d1, d2-1, d3-1);
double l8 = indexedLerp(noise->d[b3+1], d1-1, d2-1, d3-1);
int a2 = idx[a1] + i3;
int a3 = idx[a1+1] + i3;
int b2 = idx[b1] + i3;
int b3 = idx[b1+1] + i3;
double l1 = indexedLerp(idx[a2], d1, d2, d3);
double l2 = indexedLerp(idx[b2], d1-1, d2, d3);
double l3 = indexedLerp(idx[a3], d1, d2-1, d3);
double l4 = indexedLerp(idx[b3], d1-1, d2-1, d3);
double l5 = indexedLerp(idx[a2+1], d1, d2, d3-1);
double l6 = indexedLerp(idx[b2+1], d1-1, d2, d3-1);
double l7 = indexedLerp(idx[a3+1], d1, d2-1, d3-1);
double l8 = indexedLerp(idx[b3+1], d1-1, d2-1, d3-1);
l1 = lerp(t1, l1, l2);
l3 = lerp(t1, l3, l4);
@ -192,7 +190,6 @@ double sampleSimplex2D(const PerlinNoise *noise, double x, double y)
return 70.0 * t;
}
void octaveInit(OctaveNoise *noise, uint64_t *seed, PerlinNoise *octaves,
int omin, int len)
{

11
noise.h
View File

@ -2,6 +2,7 @@
#define NOISE_H_
#include "rng.h"
#include <math.h>
STRUCT(PerlinNoise)
{
@ -30,7 +31,15 @@ extern "C"
#endif
/// Helper
double maintainPrecision(double x);
static inline ATTR(hot, const)
double maintainPrecision(double x)
{ // This is a highly performance critical function that is used to correct
// progressing errors from float-maths. However, since cubiomes uses
// doubles anyway, this seems useless in practice.
//return x - round(x / 33554432.0) * 33554432.0;
return x;
}
/// Perlin noise
void perlinInit(PerlinNoise *noise, uint64_t *seed);