Compare commits

...

9 Commits

Author SHA1 Message Date
fp64 c620e6a964
Merge 00b8cc8ad6 into ae721c50ea 2024-03-19 01:10:47 -03:00
Sean Barrett ae721c50ea
Merge pull request #1609 from jeffrbig2/fix_coeffs
Fix bug in coeff gen on more than 3x downsamples with w and h equal
2024-02-12 23:49:35 -08:00
Jeff Roberts (Bellevue) 2fb057af65 remove test 2024-02-12 22:14:27 -08:00
Jeff Roberts (Bellevue) 1828f357dc Fix bug in coeff generation on more than 3x downsamples with width and height scale equal 2024-02-12 22:10:02 -08:00
Sean Barrett b7cf124628 stb_image: fix VC6 2024-02-08 13:24:06 -08:00
Jeff Roberts (Bellevue) c59da6729e Mark row0 as unused 2024-02-08 12:53:51 -08:00
Jeff Roberts (Bellevue) 7f7e3469cf clean up comments 2024-02-08 10:36:54 -08:00
Jeff Roberts (Bellevue) 7a075fe7c7 Fix 2 pixel to 1 pixel with wrap
Fix output buffer for output callback
2024-02-04 14:42:51 -08:00
fp64 00b8cc8ad6
Add derivatives 2022-10-22 10:01:15 -04:00
2 changed files with 260 additions and 137 deletions

View File

@ -1,4 +1,4 @@
/* stb_image_resize2 - v2.04 - public domain image resizing
/* stb_image_resize2 - v2.06 - public domain image resizing
by Jeff Roberts (v2) and Jorge L Rodriguez
http://github.com/nothings/stb
@ -324,11 +324,15 @@
Fabian Giesen: half float and srgb converters
Sean Barrett: API design, optimizations
Jorge L Rodriguez: Original 1.0 implementation
Aras Pranckevicius: bugfixes for 1.0
Aras Pranckevicius: bugfixes
Nathan Reed: warning fixes for 1.0
REVISIONS
2.04 (2023-11-17) Fix for rare AVX bug, shadowed symbol (thanks Nikola Smiljanic).
2.06 (2024-02-10) fix for indentical width/height 3x or more down-scaling
undersampling a single row on rare resize ratios (about 1%)
2.05 (2024-02-07) fix for 2 pixel to 1 pixel resizes with wrap (thanks Aras)
fix for output callback (thanks Julien Koenen)
2.04 (2023-11-17) fix for rare AVX bug, shadowed symbol (thanks Nikola Smiljanic).
2.03 (2023-11-01) ASAN and TSAN warnings fixed, minor tweaks.
2.00 (2023-10-10) mostly new source: new api, optimizations, simd, vertical-first, etc
(2x-5x faster without simd, 4x-12x faster with simd)
@ -3200,8 +3204,8 @@ static void stbir__calculate_in_pixel_range( int * first_pixel, int * last_pixel
if ( edge == STBIR_EDGE_WRAP )
{
if ( first <= -input_size )
first = -(input_size-1);
if ( first < -input_size )
first = -input_size;
if ( last >= (input_size*2))
last = (input_size*2) - 1;
}
@ -3392,6 +3396,12 @@ static void stbir__calculate_coefficients_for_gather_downsample( int start, int
}
}
#ifdef STBIR_RENORMALIZE_IN_FLOAT
#define STBIR_RENORM_TYPE float
#else
#define STBIR_RENORM_TYPE double
#endif
static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter_extent_info* filter_info, stbir__scale_info * scale_info, int num_contributors, stbir__contributors* contributors, float * coefficient_group, int coefficient_width )
{
int input_size = scale_info->input_full_size;
@ -3413,14 +3423,14 @@ static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter
for (n = 0; n < end; n++)
{
int i;
float filter_scale, total_filter = 0;
STBIR_RENORM_TYPE filter_scale, total_filter = 0;
int e;
// add all contribs
e = contribs->n1 - contribs->n0;
for( i = 0 ; i <= e ; i++ )
{
total_filter += coeffs[i];
total_filter += (STBIR_RENORM_TYPE) coeffs[i];
STBIR_ASSERT( ( coeffs[i] >= -2.0f ) && ( coeffs[i] <= 2.0f ) ); // check for wonky weights
}
@ -3436,10 +3446,11 @@ static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter
// if the total isn't 1.0, rescale everything
if ( ( total_filter < (1.0f-stbir__small_float) ) || ( total_filter > (1.0f+stbir__small_float) ) )
{
filter_scale = 1.0f / total_filter;
filter_scale = ((STBIR_RENORM_TYPE)1.0) / total_filter;
// scale them all
for (i = 0; i <= e; i++)
coeffs[i] *= filter_scale;
coeffs[i] = (float) ( coeffs[i] * filter_scale );
}
}
++contribs;
@ -3560,7 +3571,9 @@ static void stbir__cleanup_gathered_coefficients( stbir_edge edge, stbir__filter
filter_info->widest = widest;
}
static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row_width )
#undef STBIR_RENORM_TYPE
static int stbir__pack_coefficients( int num_contributors, stbir__contributors* contributors, float * coefficents, int coefficient_width, int widest, int row0, int row1 )
{
#define STBIR_MOVE_1( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint32*)(dest))[0] = ((stbir_uint32*)(src))[0]; }
#define STBIR_MOVE_2( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; }
@ -3569,6 +3582,10 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors*
#else
#define STBIR_MOVE_4( dest, src ) { STBIR_NO_UNROLL(dest); ((stbir_uint64*)(dest))[0] = ((stbir_uint64*)(src))[0]; ((stbir_uint64*)(dest))[1] = ((stbir_uint64*)(src))[1]; }
#endif
int row_end = row1 + 1;
STBIR__UNUSED( row0 ); // only used in an assert
if ( coefficient_width != widest )
{
float * pc = coefficents;
@ -3710,10 +3727,10 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors*
float * coeffs = coefficents + widest * ( num_contributors - 1 );
// go until no chance of clipping (this is usually less than 8 lops)
while ( ( contribs >= contributors ) && ( ( contribs->n0 + widest*2 ) >= row_width ) )
while ( ( contribs >= contributors ) && ( ( contribs->n0 + widest*2 ) >= row_end ) )
{
// might we clip??
if ( ( contribs->n0 + widest ) > row_width )
if ( ( contribs->n0 + widest ) > row_end )
{
int stop_range = widest;
@ -3732,15 +3749,15 @@ static int stbir__pack_coefficients( int num_contributors, stbir__contributors*
}
// now see if we still clip with the refined range
if ( ( contribs->n0 + stop_range ) > row_width )
if ( ( contribs->n0 + stop_range ) > row_end )
{
int new_n0 = row_width - stop_range;
int new_n0 = row_end - stop_range;
int num = contribs->n1 - contribs->n0 + 1;
int backup = contribs->n0 - new_n0;
float * from_co = coeffs + num - 1;
float * to_co = from_co + backup;
STBIR_ASSERT( ( new_n0 >= 0 ) && ( new_n0 < contribs->n0 ) );
STBIR_ASSERT( ( new_n0 >= row0 ) && ( new_n0 < contribs->n0 ) );
// move the coeffs over
while( num )
@ -3863,26 +3880,33 @@ static void stbir__calculate_filters( stbir__sampler * samp, stbir__sampler * ot
for (k = gn0 ; k <= gn1 ; k++ )
{
float gc = *g_coeffs++;
if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) )
// skip zero and denormals - must skip zeros to avoid adding coeffs beyond scatter_coefficient_width
// (which happens when pivoting from horizontal, which might have dummy zeros)
if ( ( ( gc >= stbir__small_float ) || ( gc <= -stbir__small_float ) ) )
{
if ( ( k > highest_set ) || ( scatter_contributors->n0 > scatter_contributors->n1 ) )
{
// if we are skipping over several contributors, we need to clear the skipped ones
stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1);
while ( clear_contributors < scatter_contributors )
{
clear_contributors->n0 = 0;
clear_contributors->n1 = -1;
++clear_contributors;
// if we are skipping over several contributors, we need to clear the skipped ones
stbir__contributors * clear_contributors = samp->contributors + ( highest_set + filter_pixel_margin + 1);
while ( clear_contributors < scatter_contributors )
{
clear_contributors->n0 = 0;
clear_contributors->n1 = -1;
++clear_contributors;
}
}
scatter_contributors->n0 = n;
scatter_contributors->n1 = n;
scatter_coeffs[0] = gc;
highest_set = k;
}
scatter_contributors->n0 = n;
scatter_contributors->n1 = n;
scatter_coeffs[0] = gc;
highest_set = k;
}
else
{
stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc );
else
{
stbir__insert_coeff( scatter_contributors, scatter_coeffs, n, gc );
}
STBIR_ASSERT( ( scatter_contributors->n1 - scatter_contributors->n0 + 1 ) <= scatter_coefficient_width );
}
++scatter_contributors;
scatter_coeffs += scatter_coefficient_width;
@ -5958,7 +5982,7 @@ static void stbir__encode_scanline( stbir__info const * stbir_info, void *output
// if we have an output callback, call it to send the data
if ( stbir_info->out_pixels_cb )
stbir_info->out_pixels_cb( output_buffer_data, num_pixels, row, stbir_info->user_data );
stbir_info->out_pixels_cb( output_buffer, num_pixels, row, stbir_info->user_data );
}
@ -6352,15 +6376,31 @@ static void stbir__set_sampler(stbir__sampler * samp, stbir_filter filter, stbir
// pre calculate stuff based on the above
samp->coefficient_width = stbir__get_coefficient_width(samp, samp->is_gather, user_data);
// filter_pixel_width is the conservative size in pixels of input that affect an output pixel.
// In rare cases (only with 2 pix to 1 pix with the default filters), it's possible that the
// filter will extend before or after the scanline beyond just one extra entire copy of the
// scanline (we would hit the edge twice). We don't let you do that, so we clamp the total
// width to 3x the total of input pixel (once for the scanline, once for the left side
// overhang, and once for the right side). We only do this for edge mode, since the other
// modes can just re-edge clamp back in again.
if ( edge == STBIR_EDGE_WRAP )
if ( samp->filter_pixel_width > ( scale_info->input_full_size * 2 ) ) // this can only happen when shrinking to a single pixel
samp->filter_pixel_width = scale_info->input_full_size * 2;
if ( samp->filter_pixel_width > ( scale_info->input_full_size * 3 ) )
samp->filter_pixel_width = scale_info->input_full_size * 3;
// This is how much to expand buffers to account for filters seeking outside
// the image boundaries.
samp->filter_pixel_margin = samp->filter_pixel_width / 2;
// filter_pixel_margin is the amount that this filter can overhang on just one side of either
// end of the scanline (left or the right). Since we only allow you to overhang 1 scanline's
// worth of pixels, we clamp this one side of overhang to the input scanline size. Again,
// this clamping only happens in rare cases with the default filters (2 pix to 1 pix).
if ( edge == STBIR_EDGE_WRAP )
if ( samp->filter_pixel_margin > scale_info->input_full_size )
samp->filter_pixel_margin = scale_info->input_full_size;
samp->num_contributors = stbir__get_contributors(samp, samp->is_gather);
samp->contributors_size = samp->num_contributors * sizeof(stbir__contributors);
samp->coefficients_size = samp->num_contributors * samp->coefficient_width * sizeof(float) + sizeof(float); // extra sizeof(float) is padding
@ -6996,7 +7036,7 @@ static stbir__info * stbir__alloc_internal_mem_and_build_samplers( stbir__sample
stbir__get_extents( horizontal, &info->scanline_extents );
// pack the horizontal coeffs
horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n1 + 1 );
horizontal->coefficient_width = stbir__pack_coefficients(horizontal->num_contributors, horizontal->contributors, horizontal->coefficients, horizontal->coefficient_width, horizontal->extent_info.widest, info->scanline_extents.conservative.n0, info->scanline_extents.conservative.n1 );
STBIR_MEMCPY( &info->horizontal, horizontal, sizeof( stbir__sampler ) );

View File

@ -35,15 +35,42 @@
// float stb_perlin_noise3_seed( float x,
// float y,
// float z,
// int x_wrap=0,
// int y_wrap=0,
// int z_wrap=0,
// int x_wrap,
// int y_wrap,
// int z_wrap,
// int seed)
//
// As above, but 'seed' selects from multiple different variations of the
// noise function. The current implementation only uses the bottom 8 bits
// of 'seed', but possibly in the future more bits will be used.
//
// float stb_perlin_noise3_wrap_nonpow2( float x,
// float y,
// float z,
// int x_wrap,
// int y_wrap,
// int z_wrap,
// int seed)
//
// As above, but "wrap" does not need to be a power of 2. NOTE: the result
// is different from the previous function, even for power-of-2 values. In
// the current implementation "wrap" outside [1..256] is treated as 256.
//
// float stb_perlin_noise3_derivatives( float x,
// float y,
// float z,
// int x_wrap,
// int y_wrap,
// int z_wrap,
// int seed,
// float *dx,
// float *dy,
// float *dz)
//
// As above (i.e. matches non-power-of-2 version), but also optionally
// computes partial derivatives and stores them into dx/dy/dz. Any
// of the 3 pointers can be NULL, in which case computing that
// derivative is skipped.
//
// Fractal Noise:
//
@ -71,18 +98,25 @@
// Contributors:
// Jack Mott - additional noise functions
// Jordan Peck - seeded noise
// github:fp64 - derivatives
//
#ifdef __cplusplus
// Only the basic version gets default arguments.
extern "C" float stb_perlin_noise3(float x, float y, float z, int x_wrap=0, int y_wrap=0, int z_wrap=0);
#else
extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap);
#endif
#ifdef __cplusplus
extern "C" {
#endif
extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap);
extern float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed);
extern float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed);
extern float stb_perlin_noise3_derivatives(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed, float *dx, float *dy, float *dz);
extern float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves);
extern float stb_perlin_fbm_noise3(float x, float y, float z, float lacunarity, float gain, int octaves);
extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves);
extern float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed);
#ifdef __cplusplus
}
#endif
@ -176,6 +210,21 @@ static unsigned char stb__perlin_randtab_grad_idx[512] =
9, 0, 11, 5, 10, 3, 2, 3, 5, 9, 7, 9, 8, 4, 6, 5,
};
static float stb__perlin_basistab[12][4]={
{ 1, 1, 0 },
{ -1, 1, 0 },
{ 1,-1, 0 },
{ -1,-1, 0 },
{ 1, 0, 1 },
{ -1, 0, 1 },
{ 1, 0,-1 },
{ -1, 0,-1 },
{ 0, 1, 1 },
{ 0,-1, 1 },
{ 0, 1,-1 },
{ 0,-1,-1 },
};
static float stb__perlin_lerp(float a, float b, float t)
{
return a + (b-a) * t;
@ -184,58 +233,34 @@ static float stb__perlin_lerp(float a, float b, float t)
static int stb__perlin_fastfloor(float a)
{
int ai = (int) a;
return (a < ai) ? ai-1 : ai;
return (a < (float)ai) ? ai-1 : ai;
}
// different grad function from Perlin's, but easy to modify to match reference
static float stb__perlin_grad(int grad_idx, float x, float y, float z)
{
static float basis[12][4] =
{
{ 1, 1, 0 },
{ -1, 1, 0 },
{ 1,-1, 0 },
{ -1,-1, 0 },
{ 1, 0, 1 },
{ -1, 0, 1 },
{ 1, 0,-1 },
{ -1, 0,-1 },
{ 0, 1, 1 },
{ 0,-1, 1 },
{ 0, 1,-1 },
{ 0,-1,-1 },
};
float *grad = basis[grad_idx];
float *grad = stb__perlin_basistab[grad_idx];
return grad[0]*x + grad[1]*y + grad[2]*z;
}
float stb_perlin_noise3_internal(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed)
static float stb__perlin_noise3_impl(int y0, int z0, int y1, int z1, int r0, int r1, float x, float y, float z, float *dx, float *dy, float *dz)
{
float u,v,w;
float n000,n001,n010,n011,n100,n101,n110,n111;
float n00,n01,n10,n11;
float n0,n1;
float n;
unsigned int x_mask = (x_wrap-1) & 255;
unsigned int y_mask = (y_wrap-1) & 255;
unsigned int z_mask = (z_wrap-1) & 255;
int px = stb__perlin_fastfloor(x);
int py = stb__perlin_fastfloor(y);
int pz = stb__perlin_fastfloor(z);
int x0 = px & x_mask, x1 = (px+1) & x_mask;
int y0 = py & y_mask, y1 = (py+1) & y_mask;
int z0 = pz & z_mask, z1 = (pz+1) & z_mask;
int r0,r1, r00,r01,r10,r11;
int r00,r01,r10,r11;
int i;
float *out[3]={dx,dy,dz};
#define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a)
#define stb__perlin_dease(a) (((a*30-60)*a + 30) * a * a)
x -= px; u = stb__perlin_ease(x);
y -= py; v = stb__perlin_ease(y);
z -= pz; w = stb__perlin_ease(z);
r0 = stb__perlin_randtab[x0+seed];
r1 = stb__perlin_randtab[x1+seed];
u = stb__perlin_ease(x);
v = stb__perlin_ease(y);
w = stb__perlin_ease(z);
r00 = stb__perlin_randtab[r0+y0];
r01 = stb__perlin_randtab[r0+y1];
@ -259,7 +284,121 @@ float stb_perlin_noise3_internal(float x, float y, float z, int x_wrap, int y_wr
n0 = stb__perlin_lerp(n00,n01,v);
n1 = stb__perlin_lerp(n10,n11,v);
return stb__perlin_lerp(n0,n1,u);
n = stb__perlin_lerp(n0,n1,u);
for(i = 0; i < 3; i++)
{
float d000,d001,d010,d011,d100,d101,d110,d111;
float d00,d01,d10,d11;
float d0,d1;
float d;
float t00,t01,t10,t11;
float t0,t1;
float t;
float u0=1.0f-u, v0=1.0f-v, w0=1.0f-w, u1=u, v1=v, w1=w;
if(out[i] == 0) continue;
if(i == 0) {u1 = stb__perlin_dease(x); u0 = -u1;}
if(i == 1) {v1 = stb__perlin_dease(y); v0 = -v1;}
if(i == 2) {w1 = stb__perlin_dease(z); w0 = -w1;}
d000 = stb__perlin_basistab[stb__perlin_randtab_grad_idx[r00+z0]][i];
d001 = stb__perlin_basistab[stb__perlin_randtab_grad_idx[r00+z1]][i];
d010 = stb__perlin_basistab[stb__perlin_randtab_grad_idx[r01+z0]][i];
d011 = stb__perlin_basistab[stb__perlin_randtab_grad_idx[r01+z1]][i];
d100 = stb__perlin_basistab[stb__perlin_randtab_grad_idx[r10+z0]][i];
d101 = stb__perlin_basistab[stb__perlin_randtab_grad_idx[r10+z1]][i];
d110 = stb__perlin_basistab[stb__perlin_randtab_grad_idx[r11+z0]][i];
d111 = stb__perlin_basistab[stb__perlin_randtab_grad_idx[r11+z1]][i];
d00 = stb__perlin_lerp(d000,d001,w);
d01 = stb__perlin_lerp(d010,d011,w);
d10 = stb__perlin_lerp(d100,d101,w);
d11 = stb__perlin_lerp(d110,d111,w);
d0 = stb__perlin_lerp(d00,d01,v);
d1 = stb__perlin_lerp(d10,d11,v);
d = stb__perlin_lerp(d0,d1,u);
t00 = n000*w0 + n001*w1;
t01 = n010*w0 + n011*w1;
t10 = n100*w0 + n101*w1;
t11 = n110*w0 + n111*w1;
t0 = t00*v0 + t01*v1;
t1 = t10*v0 + t11*v1;
t = t0*u0 + t1*u1;
*(out[i]) = (d + t);
}
return n;
}
static float stb_perlin_noise3_internal(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed)
{
int x_mask = (x_wrap-1) & 255;
int y_mask = (y_wrap-1) & 255;
int z_mask = (z_wrap-1) & 255;
int px = stb__perlin_fastfloor(x);
int py = stb__perlin_fastfloor(y);
int pz = stb__perlin_fastfloor(z);
int x0 = px & x_mask, x1 = (px+1) & x_mask;
int y0 = py & y_mask, y1 = (py+1) & y_mask;
int z0 = pz & z_mask, z1 = (pz+1) & z_mask;
seed &= 255;
int r0 = stb__perlin_randtab[x0+seed];
int r1 = stb__perlin_randtab[x1+seed];
x -= (float)px;
y -= (float)py;
z -= (float)pz;
return stb__perlin_noise3_impl(y0,z0,y1,z1,r0,r1,x,y,z,0,0,0);
}
float stb_perlin_noise3_derivatives(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed,float *dx, float *dy, float *dz)
{
int px = stb__perlin_fastfloor(x);
int py = stb__perlin_fastfloor(y);
int pz = stb__perlin_fastfloor(z);
int x0, x1, y0, y1, z0, z1;
int r0, r1;
x -= (float)px;
y -= (float)py;
z -= (float)pz;
seed &= 255;
if(((x_wrap & (x_wrap-1)) | (y_wrap & (y_wrap-1)) | (z_wrap & (z_wrap-1))))
{
int x_wrap2 = ((x_wrap>0 && x_wrap<256) ? x_wrap : 256);
int y_wrap2 = ((y_wrap>0 && y_wrap<256) ? y_wrap : 256);
int z_wrap2 = ((z_wrap>0 && z_wrap<256) ? z_wrap : 256);
x0 = px % x_wrap2;
y0 = py % y_wrap2;
z0 = pz % z_wrap2;
if (x0 < 0) x0 += x_wrap2;
if (y0 < 0) y0 += y_wrap2;
if (z0 < 0) z0 += z_wrap2;
x1 = (x0+1) % x_wrap2;
y1 = (y0+1) % y_wrap2;
z1 = (z0+1) % z_wrap2;
}
else
{
int x_mask = (x_wrap-1) & 255;
int y_mask = (y_wrap-1) & 255;
int z_mask = (z_wrap-1) & 255;
x0 = px & x_mask; x1 = (px+1) & x_mask;
y0 = py & y_mask; y1 = (py+1) & y_mask;
z0 = pz & z_mask; z1 = (pz+1) & z_mask;
}
r0 = stb__perlin_randtab[x0];
r0 = stb__perlin_randtab[r0+seed];
r1 = stb__perlin_randtab[x1];
r1 = stb__perlin_randtab[r1+seed];
return stb__perlin_noise3_impl(y0,z0,y1,z1,r0,r1,x,y,z,dx,dy,dz);
}
float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap)
@ -269,7 +408,12 @@ float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z
float stb_perlin_noise3_seed(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, int seed)
{
return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap, (unsigned char) seed);
return stb_perlin_noise3_internal(x,y,z,x_wrap,y_wrap,z_wrap,(unsigned char)seed);
}
float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed)
{
return stb_perlin_noise3_derivatives(x,y,z,x_wrap,y_wrap,z_wrap,(int)seed,0,0,0);
}
float stb_perlin_ridge_noise3(float x, float y, float z, float lacunarity, float gain, float offset, int octaves)
@ -322,67 +466,6 @@ float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity,
}
return sum;
}
float stb_perlin_noise3_wrap_nonpow2(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap, unsigned char seed)
{
float u,v,w;
float n000,n001,n010,n011,n100,n101,n110,n111;
float n00,n01,n10,n11;
float n0,n1;
int px = stb__perlin_fastfloor(x);
int py = stb__perlin_fastfloor(y);
int pz = stb__perlin_fastfloor(z);
int x_wrap2 = (x_wrap ? x_wrap : 256);
int y_wrap2 = (y_wrap ? y_wrap : 256);
int z_wrap2 = (z_wrap ? z_wrap : 256);
int x0 = px % x_wrap2, x1;
int y0 = py % y_wrap2, y1;
int z0 = pz % z_wrap2, z1;
int r0,r1, r00,r01,r10,r11;
if (x0 < 0) x0 += x_wrap2;
if (y0 < 0) y0 += y_wrap2;
if (z0 < 0) z0 += z_wrap2;
x1 = (x0+1) % x_wrap2;
y1 = (y0+1) % y_wrap2;
z1 = (z0+1) % z_wrap2;
#define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a)
x -= px; u = stb__perlin_ease(x);
y -= py; v = stb__perlin_ease(y);
z -= pz; w = stb__perlin_ease(z);
r0 = stb__perlin_randtab[x0];
r0 = stb__perlin_randtab[r0+seed];
r1 = stb__perlin_randtab[x1];
r1 = stb__perlin_randtab[r1+seed];
r00 = stb__perlin_randtab[r0+y0];
r01 = stb__perlin_randtab[r0+y1];
r10 = stb__perlin_randtab[r1+y0];
r11 = stb__perlin_randtab[r1+y1];
n000 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z0], x , y , z );
n001 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r00+z1], x , y , z-1 );
n010 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z0], x , y-1, z );
n011 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r01+z1], x , y-1, z-1 );
n100 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z0], x-1, y , z );
n101 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r10+z1], x-1, y , z-1 );
n110 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z0], x-1, y-1, z );
n111 = stb__perlin_grad(stb__perlin_randtab_grad_idx[r11+z1], x-1, y-1, z-1 );
n00 = stb__perlin_lerp(n000,n001,w);
n01 = stb__perlin_lerp(n010,n011,w);
n10 = stb__perlin_lerp(n100,n101,w);
n11 = stb__perlin_lerp(n110,n111,w);
n0 = stb__perlin_lerp(n00,n01,v);
n1 = stb__perlin_lerp(n10,n11,v);
return stb__perlin_lerp(n0,n1,u);
}
#endif // STB_PERLIN_IMPLEMENTATION
/*