mirror of https://github.com/nothings/stb.git
Compare commits
9 Commits
df964d64ff
...
c620e6a964
Author | SHA1 | Date |
---|---|---|
fp64 | c620e6a964 | |
Sean Barrett | ae721c50ea | |
Jeff Roberts (Bellevue) | 2fb057af65 | |
Jeff Roberts (Bellevue) | 1828f357dc | |
Sean Barrett | b7cf124628 | |
Jeff Roberts (Bellevue) | c59da6729e | |
Jeff Roberts (Bellevue) | 7f7e3469cf | |
Jeff Roberts (Bellevue) | 7a075fe7c7 | |
fp64 | 00b8cc8ad6 |
|
@ -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 ) );
|
||||
|
||||
|
|
289
stb_perlin.h
289
stb_perlin.h
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue