bool raycast(game* g, vec2 from, vec2 to) { ivec2 cur(fast_floor(from.x), fast_floor(from.y)); ivec2 end(fast_floor(to.x), fast_floor(to.y)); ivec2 sign(sign(to.x - from.x), sign(to.y - from.y)); vec2 abs_delta(abs(to.x - from.x), abs(to.y - from.y)); vec2 delta_t(vec2(1.0f) / abs_delta); vec2 lb(to_vec2(cur)); vec2 ub(lb + vec2(1.0f)); vec2 t(vec2((from.x > to.x) ? (from.x - lb.x) : (ub.x - from.x), (from.y > to.y) ? (from.y - lb.y) : (ub.y - from.y)) / abs_delta); for(;;) { if (g->is_raycast_solid(cur.x, cur.y)) return true; if (t.x <= t.y) { if (cur.x == end.x) break; t.x += delta_t.x; cur.x += sign.x; } else { if (cur.y == end.y) break; t.y += delta_t.y; cur.y += sign.y; } } return false; }
chunk_pos& chunk_pos::operator= (const entity_pos &other) { this->x = fast_floor (other.x) / 16; this->z = fast_floor (other.z) / 16; return *this; }
block_pos& block_pos::operator= (const entity_pos &other) { this->x = fast_floor (other.x); this->y = fast_floor (other.y); this->z = fast_floor (other.z); //if (this->y < 0) this->y = 0; //if (this->y > 255) this->y = 255; return *this; }
float raw_noise_2d(float x, float y, const uint8_t* perm) { const float F2 = 0.5f * (std::sqrt(3.0f) - 1.0f); float s = (x + y) * F2; int32_t i = fast_floor(x + s); int32_t j = fast_floor(y + s); const float G2 = (3.0f - std::sqrt(3.0f)) / 6.0f; float t = (i + j) * G2; float x0 = x - (i - t); float y0 = y - (j - t); uint8_t i1 = 0; uint8_t j1 = 1; if(x0 > y0) { i1 = 1; j1 = 0; } float x1 = x0 - i1 + G2; float y1 = y0 - j1 + G2; float x2 = x0 - 1.0f + 2.0f * G2; float y2 = y0 - 1.0f + 2.0f * G2; uint8_t ii = i & 255; uint8_t jj = j & 255; uint8_t gi0 = perm[ii + perm[jj ] ] % 12; uint8_t gi1 = perm[ii + perm[jj + j1] + i1] % 12; uint8_t gi2 = perm[ii + perm[jj + 1 ] + 1 ] % 12; float t0 = 0.5f - x0 * x0 - y0 * y0; float t1 = 0.5f - x1 * x1 - y1 * y1; float t2 = 0.5f - x2 * x2 - y2 * y2; float n0 = (t0 < 0) ? 0.0f : t0*t0*t0*t0 * dot(grad3[gi0], x0, y0); float n1 = (t1 < 0) ? 0.0f : t1*t1*t1*t1 * dot(grad3[gi1], x1, y1); float n2 = (t2 < 0) ? 0.0f : t2*t2*t2*t2 * dot(grad3[gi2], x2, y2); return 70.0f * (n0 + n1 + n2); }
// Classic Perlin noise, 3D version float base(float x, float y) { x *= xscale; //replace with multiplication y *= xscale; //get grid point int X = fast_floor(x); int Y = fast_floor(y); x = x - X; y = y - Y; int gi00 = get_gradient(X+0,Y+0); int gi01 = get_gradient(X+0,Y+1); int gi10 = get_gradient(X+1,Y+0); int gi11 = get_gradient(X+1,Y+1); // Calculate noise contributions from each of the eight corners float n00= dot(grad+2*gi00, x, y); float n10= dot(grad+2*gi10, x-1, y); float n01= dot(grad+2*gi01, x, y-1); float n11= dot(grad+2*gi11, x-1, y-1); // Compute the fade curve value for each of x, y, z #if 1 float u = fade(x); float v = fade(y); #else float u = x; float v = y; #endif // Interpolate along x the contributions from each of the corners float nx00 = mix(n00, n10, u); float nx10 = mix(n01, n11, u); // Interpolate the four results along y float nxy = mix(nx00, nx10, v); if (nxy < -1 || nxy > 1 ) printf("Error: noise %f \n", nxy); //return nxy / 0.707106781f; //-1 to 1 return nxy; //-1 to 1 }
aabb2 cast_aabb(game* g, aabb2 self, vec2 delta, int* clipped) { aabb2 bounds(expand_toward(self, delta)); int x0 = fast_floor(bounds.min.x); int y0 = fast_floor(bounds.min.y); int x1 = fast_floor(bounds.max.x); int y1 = fast_floor(bounds.max.y); vec2 clipped_delta = delta; for(int x = x0; x <= x1; x++) { for(int y = y0; y <= y1; y++) { if (g->get_tile(x, y) != TT_EMPTY) { clipped_delta.x = clip_x(aabb2(vec2((float)x, (float)y), vec2((float)(x + 1), (float)(y + 1))), self, clipped_delta.x); } } } self.min.x += clipped_delta.x; self.max.x += clipped_delta.x; for(int x = x0; x <= x1; x++) { for(int y = y0; y <= y1; y++) { if (g->get_tile(x, y) != TT_EMPTY) { clipped_delta.y = clip_y(aabb2(vec2((float)x, (float)y), vec2((float)(x + 1), (float)(y + 1))), self, clipped_delta.y); } } } self.min.y += clipped_delta.y; self.max.y += clipped_delta.y; if (clipped) { *clipped = 0; if (delta.x != clipped_delta.x) *clipped |= (delta.x > 0.0f) ? CLIPPED_XP : CLIPPED_XN; if (delta.y != clipped_delta.y) *clipped |= (delta.y > 0.0f) ? CLIPPED_YP : CLIPPED_YN; } return self; }
/** @brief MATLAB Driver. **/ void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { int M,N,S=0,smin=0,K,num_levels=0 ; const int* dimensions ; const double* P_pt ; const double* G_pt ; float* descr_pt ; float* buffer_pt ; float sigma0 ; float magnif = 3.0f ; /* Spatial bin extension factor. */ int NBP = 4 ; /* Number of bins for one spatial direction (even). */ int NBO = 8 ; /* Number of bins for the ortientation. */ int mode = NOSCALESPACE ; int buffer_size=0; enum {IN_G=0,IN_P,IN_SIGMA0,IN_S,IN_SMIN} ; enum {OUT_L=0} ; /* ------------------------------------------------------------------ ** Check the arguments ** --------------------------------------------------------------- */ if (nin < 3) { mexErrMsgTxt("At least three arguments are required") ; } else if (nout > 1) { mexErrMsgTxt("Too many output arguments."); } if( !uIsRealScalar(in[IN_SIGMA0]) ) { mexErrMsgTxt("SIGMA0 should be a real scalar") ; } if(!mxIsDouble(in[IN_G]) || mxGetNumberOfDimensions(in[IN_G]) > 3) { mexErrMsgTxt("G should be a real matrix or 3-D array") ; } sigma0 = (float) *mxGetPr(in[IN_SIGMA0]) ; dimensions = mxGetDimensions(in[IN_G]) ; M = dimensions[0] ; N = dimensions[1] ; G_pt = mxGetPr(in[IN_G]) ; P_pt = mxGetPr(in[IN_P]) ; K = mxGetN(in[IN_P]) ; if( !uIsRealMatrix(in[IN_P],-1,-1)) { mexErrMsgTxt("P should be a real matrix") ; } if ( mxGetM(in[IN_P]) == 4) { /* Standard (scale space) mode */ mode = SCALESPACE ; num_levels = dimensions[2] ; if(nin < 5) { mexErrMsgTxt("Five arguments are required in standard mode") ; } if( !uIsRealScalar(in[IN_S]) ) { mexErrMsgTxt("S should be a real scalar") ; } if( !uIsRealScalar(in[IN_SMIN]) ) { mexErrMsgTxt("SMIN should be a real scalar") ; } if( !uIsRealMatrix(in[IN_P],4,-1)) { mexErrMsgTxt("When the e mode P should be a 4xK matrix.") ; } S = (int)(*mxGetPr(in[IN_S])) ; smin = (int)(*mxGetPr(in[IN_SMIN])) ; } else if ( mxGetM(in[IN_P]) == 3 ) { mode = NOSCALESPACE ; num_levels = 1 ; S = 1 ; smin = 0 ; } else { mexErrMsgTxt("P should be either a 3xK or a 4xK matrix.") ; } /* Parse the property-value pairs */ { char str [80] ; int arg = (mode == SCALESPACE) ? IN_SMIN + 1 : IN_SIGMA0 + 1 ; while(arg < nin) { int k ; if( !uIsString(in[arg],-1) ) { mexErrMsgTxt("The first argument in a property-value pair" " should be a string") ; } mxGetString(in[arg], str, 80) ; #ifdef WINDOWS for(k = 0 ; properties[k] && strcmpi(str, properties[k]) ; ++k) ; #else for(k = 0 ; properties[k] && strcasecmp(str, properties[k]) ; ++k) ; #endif switch (k) { case PROP_NBP: if( !uIsRealScalar(in[arg+1]) ) { mexErrMsgTxt("'NumSpatialBins' should be real scalar") ; } NBP = (int) *mxGetPr(in[arg+1]) ; if( NBP <= 0 || (NBP & 0x1) ) { mexErrMsgTxt("'NumSpatialBins' must be positive and even") ; } break ; case PROP_NBO: if( !uIsRealScalar(in[arg+1]) ) { mexErrMsgTxt("'NumOrientBins' should be a real scalar") ; } NBO = (int) *mxGetPr(in[arg+1]) ; if( NBO <= 0 ) { mexErrMsgTxt("'NumOrientlBins' must be positive") ; } break ; case PROP_MAGNIF: if( !uIsRealScalar(in[arg+1]) ) { mexErrMsgTxt("'Magnif' should be a real scalar") ; } magnif = (float) *mxGetPr(in[arg+1]) ; if( magnif <= 0 ) { mexErrMsgTxt("'Magnif' must be positive") ; } break ; case PROP_UNKNOWN: mexErrMsgTxt("Property unknown.") ; break ; } arg += 2 ; } } /* ----------------------------------------------------------------- * Pre-compute gradient and angles * -------------------------------------------------------------- */ /* Alloc two buffers and make sure their size is multiple of 128 for * better alignment (used also by the Altivec code below.) */ buffer_size = (M*N*num_levels + 0x7f) & (~ 0x7f) ; buffer_pt = (float*) mxMalloc( sizeof(float) * 2 * buffer_size ) ; descr_pt = (float*) mxCalloc( NBP*NBP*NBO*K, sizeof(float) ) ; { /* Offsets to move in the scale space. */ const int yo = 1 ; const int xo = M ; const int so = M*N ; int x,y,s ; #define at(x,y) (*(pt + (x)*xo + (y)*yo)) /* Compute the gradient */ for(s = 0 ; s < num_levels ; ++s) { const double* pt = G_pt + s*so ; for(x = 1 ; x < N-1 ; ++x) { for(y = 1 ; y < M-1 ; ++y) { float Dx = 0.5 * ( at(x+1,y) - at(x-1,y) ) ; float Dy = 0.5 * ( at(x,y+1) - at(x,y-1) ) ; buffer_pt[(x*xo+y*yo+s*so) + 0 ] = Dx ; buffer_pt[(x*xo+y*yo+s*so) + buffer_size] = Dy ; } } } /* Compute angles and modules */ { float* pt = buffer_pt ; int j = 0 ; while (j < N*M*num_levels) { #if defined( MACOSX ) && defined( __ALTIVEC__ ) if( ((unsigned int)pt & 0x7) == 0 && j+3 < N*M*num_levels ) { /* If aligned to 128 bit and there are at least 4 pixels left */ float4 a, b, c, d ; a.vec = vec_ld(0,(vector float*)(pt )) ; b.vec = vec_ld(0,(vector float*)(pt + buffer_size)) ; c.vec = vatan2f(b.vec,a.vec) ; a.x[0] = a.x[0]*a.x[0]+b.x[0]*b.x[0] ; a.x[1] = a.x[1]*a.x[1]+b.x[1]*b.x[1] ; a.x[2] = a.x[2]*a.x[2]+b.x[2]*b.x[2] ; a.x[3] = a.x[3]*a.x[3]+b.x[3]*b.x[3] ; d.vec = vsqrtf(a.vec) ; vec_st(c.vec,0,(vector float*)(pt + buffer_size)) ; vec_st(d.vec,0,(vector float*)(pt )) ; j += 4 ; pt += 4 ; } else { #endif float Dx = *(pt ) ; float Dy = *(pt + buffer_size) ; *(pt ) = sqrtf(Dx*Dx + Dy*Dy) ; if (*pt > 0) *(pt + buffer_size) = atan2f(Dy, Dx) ; else *(pt + buffer_size) = 0 ; j += 1 ; pt += 1 ; #if defined( MACOSX ) && defined( __ALTIVEC__ ) } #endif } } } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ if(K > 0) { int p ; /* Offsets to move in the buffer */ const int yo = 1 ; const int xo = M ; const int so = M*N ; /* Offsets to move in the descriptor. */ /* Use Lowe's convention. */ const int binto = 1 ; const int binyo = NBO * NBP ; const int binxo = NBO ; const int bino = NBO * NBP * NBP ; for(p = 0 ; p < K ; ++p, descr_pt += bino) { /* The SIFT descriptor is a three dimensional histogram of the position * and orientation of the gradient. There are NBP bins for each spatial * dimesions and NBO bins for the orientation dimesion, for a total of * NBP x NBP x NBO bins. * * The support of each spatial bin has an extension of SBP = 3sigma * pixels, where sigma is the scale of the keypoint. Thus all the bins * together have a support SBP x NBP pixels wide . Since weighting and * interpolation of pixel is used, another half bin is needed at both * ends of the extension. Therefore, we need a square window of SBP x * (NBP + 1) pixels. Finally, since the patch can be arbitrarly rotated, * we need to consider a window 2W += sqrt(2) x SBP x (NBP + 1) pixels * wide. */ const float x = (float) *P_pt++ ; const float y = (float) *P_pt++ ; const float s = (float) (mode == SCALESPACE) ? (*P_pt++) : 0.0 ; const float theta0 = (float) *P_pt++ ; const float st0 = sinf(theta0) ; const float ct0 = cosf(theta0) ; const int xi = (int) floor(x+0.5) ; /* Round-off */ const int yi = (int) floor(y+0.5) ; const int si = (int) floor(s+0.5) - smin ; const float sigma = sigma0 * powf(2, s / S) ; const float SBP = magnif * sigma ; const int W = (int) floor( sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5) ; int bin ; int dxi ; int dyi ; const float* pt ; float* dpt ; /* Check that keypoints are within bounds . */ if(xi < 0 || xi > N-1 || yi < 0 || yi > M-1 || ((mode==SCALESPACE) && (si < 0 || si > dimensions[2]-1) ) ) continue ; /* Center the scale space and the descriptor on the current keypoint. * Note that dpt is pointing to the bin of center (SBP/2,SBP/2,0). */ pt = buffer_pt + xi*xo + yi*yo + si*so ; dpt = descr_pt + (NBP/2) * binyo + (NBP/2) * binxo ; #define atd(dbinx,dbiny,dbint) (*(dpt + (dbint)*binto + (dbiny)*binyo + (dbinx)*binxo)) /* * Process each pixel in the window and in the (1,1)-(M-1,N-1) * rectangle. */ for(dxi = max(-W, 1-xi) ; dxi <= min(+W, N-2-xi) ; ++dxi) { for(dyi = max(-W, 1-yi) ; dyi <= min(+W, M-2-yi) ; ++dyi) { /* Compute the gradient. */ float mod = *(pt + dxi*xo + dyi*yo + 0 ) ; float angle = *(pt + dxi*xo + dyi*yo + buffer_size ) ; #ifdef LOWE_COMPATIBLE float theta = fast_mod(-angle + theta0) ; #else float theta = fast_mod(angle - theta0) ; #endif /* Get the fractional displacement. */ float dx = ((float)(xi+dxi)) - x; float dy = ((float)(yi+dyi)) - y; /* Get the displacement normalized w.r.t. the keypoint orientation * and extension. */ float nx = ( ct0 * dx + st0 * dy) / SBP ; float ny = (-st0 * dx + ct0 * dy) / SBP ; float nt = NBO * theta / (2*M_PI) ; /* Get the gaussian weight of the sample. The gaussian window * has a standard deviation of NBP/2. Note that dx and dy are in * the normalized frame, so that -NBP/2 <= dx <= NBP/2. */ const float wsigma = NBP/2 ; float win = expf(-(nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ; /* The sample will be distributed in 8 adijacient bins. * Now we get the ``lower-left'' bin. */ int binx = fast_floor( nx - 0.5 ) ; int biny = fast_floor( ny - 0.5 ) ; int bint = fast_floor( nt ) ; float rbinx = nx - (binx+0.5) ; float rbiny = ny - (biny+0.5) ; float rbint = nt - bint ; int dbinx ; int dbiny ; int dbint ; /* Distribute the current sample into the 8 adijacient bins. */ for(dbinx = 0 ; dbinx < 2 ; ++dbinx) { for(dbiny = 0 ; dbiny < 2 ; ++dbiny) { for(dbint = 0 ; dbint < 2 ; ++dbint) { if( binx+dbinx >= -(NBP/2) && binx+dbinx < (NBP/2) && biny+dbiny >= -(NBP/2) && biny+dbiny < (NBP/2) ) { float weight = win * mod * fabsf(1 - dbinx - rbinx) * fabsf(1 - dbiny - rbiny) * fabsf(1 - dbint - rbint) ; atd(binx+dbinx, biny+dbiny, (bint+dbint) % NBO) += weight ; } } } } } } { /* Normalize the histogram to L2 unit length. */ normalize_histogram(descr_pt, descr_pt + NBO*NBP*NBP) ; /* Truncate at 0.2. */ for(bin = 0; bin < NBO*NBP*NBP ; ++bin) { if (descr_pt[bin] > 0.2) descr_pt[bin] = 0.2; } /* Normalize again. */ normalize_histogram(descr_pt, descr_pt + NBO*NBP*NBP) ; } } } /* Restore pointer to the beginning of the descriptors. */ descr_pt -= NBO*NBP*NBP*K ; { int k ; double* L_pt ; out[OUT_L] = mxCreateDoubleMatrix(NBP*NBP*NBO, K, mxREAL) ; L_pt = mxGetPr(out[OUT_L]) ; for(k = 0 ; k < NBP*NBP*NBO*K ; ++k) { L_pt[k] = descr_pt[k] ; } } mxFree(descr_pt) ; mxFree(buffer_pt) ; }
static float generate(float x, float y) { const float F2 = 0.366025403f; // F2 = 0.5*(sqrt(3.0)-1.0) const float G2 = 0.211324865f; // G2 = (3.0-Math.sqrt(3.0))/6.0 float n0, n1, n2; // Noise contributions from the three corners // Skew the input space to determine which simplex cell we're in float s = (x + y) * F2; // Hairy factor for 2D float xs = x + s; float ys = y + s; sint32 i = fast_floor(xs); sint32 j = fast_floor(ys); float t = (float)(i + j) * G2; float X0 = i - t; // Unskew the cell origin back to (x,y) space float Y0 = j - t; float x0 = x - X0; // The x,y distances from the cell origin float y0 = y - Y0; // For the 2D case, the simplex shape is an equilateral triangle. // Determine which simplex we are in. sint32 i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords if (x0 > y0) { i1 = 1; j1 = 0; } // lower triangle, XY order: (0,0)->(1,0)->(1,1) else { i1 = 0; j1 = 1; } // upper triangle, YX order: (0,0)->(0,1)->(1,1) // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where // c = (3-sqrt(3))/6 float x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords float y1 = y0 - j1 + G2; float x2 = x0 - 1.0f + 2.0f * G2; // Offsets for last corner in (x,y) unskewed coords float y2 = y0 - 1.0f + 2.0f * G2; // Wrap the integer indices at 256, to avoid indexing perm[] out of bounds sint32 ii = i % 256; sint32 jj = j % 256; // Calculate the contribution from the three corners float t0 = 0.5f - x0 * x0 - y0 * y0; if (t0 < 0.0f) n0 = 0.0f; else { t0 *= t0; n0 = t0 * t0 * grad(perm[ii + perm[jj]], x0, y0); } float t1 = 0.5f - x1 * x1 - y1 * y1; if (t1 < 0.0f) n1 = 0.0f; else { t1 *= t1; n1 = t1 * t1 * grad(perm[ii + i1 + perm[jj + j1]], x1, y1); } float t2 = 0.5f - x2 * x2 - y2 * y2; if (t2 < 0.0f) n2 = 0.0f; else { t2 *= t2; n2 = t2 * t2 * grad(perm[ii + 1 + perm[jj + 1]], x2, 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 40.0f * (n0 + n1 + n2); // TODO: The scale factor is preliminary! }
#include "catch/catch.hpp" #include "cata_utility.h" #include <cmath> #include <random> TEST_CASE( "fast_floor", "[math]" ) { REQUIRE( fast_floor( -2.0 ) == -2 ); REQUIRE( fast_floor( -1.9 ) == -2 ); REQUIRE( fast_floor( -1.1 ) == -2 ); REQUIRE( fast_floor( -1.0 ) == -1 ); REQUIRE( fast_floor( -0.9 ) == -1 ); REQUIRE( fast_floor( -0.1 ) == -1 ); REQUIRE( fast_floor( 0.0 ) == 0 ); REQUIRE( fast_floor( 0.1 ) == 0 ); REQUIRE( fast_floor( 0.9 ) == 0 ); REQUIRE( fast_floor( 1.0 ) == 1 ); REQUIRE( fast_floor( 1.1 ) == 1 ); REQUIRE( fast_floor( 1.9 ) == 1 ); REQUIRE( fast_floor( 2.0 ) == 2 ); REQUIRE( fast_floor( 2.1 ) == 2 ); REQUIRE( fast_floor( 2.9 ) == 2 ); std::random_device rd; std::mt19937 mt( rd() ); std::uniform_real_distribution<double> dist( -10.0, 10.0 ); for( size_t i = 0; i != 1000; ++i ) { double val = dist( mt );
// Classic Perlin noise, 3D version float base(float x, float y, float z) { /* // Find unit grid cell containing point int X = fast_floor(x); int Y = fast_floor(y); int Z = fast_floor(z); // Get relative xyz coordinates of point within that cell x = x - X; y = y - Y; z = z - Z; // Wrap the integer cells at 255 (smaller integer period can be introduced here) X = X & 255; Y = Y & 255; Z = Z & 255; */ x /= 8.0; //replace with multiplication y /= 8.0; z /= 4.0; //get grid point int X = fast_floor(x); int Y = fast_floor(y); int Z = fast_floor(z); //get interpolation ratio //if (z >= 32 || z < 0) printf("ERROR1 z = %f \n", z); x = x - X; y = y - Y; z = z - Z; //if (z >= 32 || z < 0) printf("ERROR2 z = %f \n", z); //if (x<0 || y<0 || z<0) printf("x,y,z= %f %f %f \n", x,y,z); //if (z >= 32) printf("x,y,z= %f %f %f X,Y,Z= %i %i %i \n", x+X,y+Y,z+Z,X,Y,Z); // Calculate a set of eight hashed gradient indices int gi000 = get_gradient(X+0,Y+0,Z+0); int gi001 = get_gradient(X+0,Y+0,Z+1); int gi010 = get_gradient(X+0,Y+1,Z+0); int gi011 = get_gradient(X+0,Y+1,Z+1); int gi100 = get_gradient(X+1,Y+0,Z+0); int gi101 = get_gradient(X+1,Y+0,Z+1); int gi110 = get_gradient(X+1,Y+1,Z+0); int gi111 = get_gradient(X+1,Y+1,Z+1); /* int gi000 = perm[X+perm[Y+perm[Z]]] % 12; int gi001 = perm[X+perm[Y+perm[Z+1]]] % 12; int gi010 = perm[X+perm[Y+1+perm[Z]]] % 12; int gi011 = perm[X+perm[Y+1+perm[Z+1]]] % 12; int gi100 = perm[X+1+perm[Y+perm[Z]]] % 12; int gi101 = perm[X+1+perm[Y+perm[Z+1]]] % 12; int gi110 = perm[X+1+perm[Y+1+perm[Z]]] % 12; int gi111 = perm[X+1+perm[Y+1+perm[Z+1]]] % 12; */ // The gradients of each corner are now: // g000 = grad3[gi000]; // g001 = grad3[gi001]; // g010 = grad3[gi010]; // g011 = grad3[gi011]; // g100 = grad3[gi100]; // g101 = grad3[gi101]; // g110 = grad3[gi110]; // g111 = grad3[gi111]; // Calculate noise contributions from each of the eight corners float n000= dot(_grad3[gi000], x, y, z); float n100= dot(_grad3[gi100], x-1, y, z); float n010= dot(_grad3[gi010], x, y-1, z); float n110= dot(_grad3[gi110], x-1, y-1, z); float n001= dot(_grad3[gi001], x, y, z-1); float n101= dot(_grad3[gi101], x-1, y, z-1); float n011= dot(_grad3[gi011], x, y-1, z-1); float n111= dot(_grad3[gi111], x-1, y-1, z-1); // Compute the fade curve value for each of x, y, z #if 1 float u = fade(x); float v = fade(y); float w = fade(z); #else float u = x; float v = y; float w = z; #endif // Interpolate along x the contributions from each of the corners float nx00 = mix(n000, n100, u); float nx01 = mix(n001, n101, u); float nx10 = mix(n010, n110, u); float nx11 = mix(n011, n111, u); // Interpolate the four results along y float nxy0 = mix(nx00, nx10, v); float nxy1 = mix(nx01, nx11, v); // Interpolate the two last results along z float nxyz = mix(nxy0, nxy1, w); return nxyz * 0.707106781; //-1 to 1 }
float raw_noise_3d(float x, float y, float z, const uint8_t* perm) { constexpr float F3 = 1.0f / 3.0f; float s = (x + y + z) * F3; float i = fast_floor(x + s); float j = fast_floor(y + s); float k = fast_floor(z + s); constexpr float G3 = 1.0f / 6.0f; float t = (i + j + k) * G3; float x0 = x - (i - t); float y0 = y - (j - t); float z0 = z - (k - t); uint8_t i1 = 0, j1 = 1, k1 = 0; uint8_t i2 = 1, j2 = 1, k2 = 0; if(x0 >= y0) { if(y0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } else if(x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } } else { if(y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } else if(x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } } float x1 = x0 - i1 + G3; float y1 = y0 - j1 + G3; float z1 = z0 - k1 + G3; float x2 = x0 - i2 + G3 * 2.0f; float y2 = y0 - j2 + G3 * 2.0f; float z2 = z0 - k2 + G3 * 2.0f; float x3 = x0 - 1.0f + G3 * 3.0f; float y3 = y0 - 1.0f + G3 * 3.0f; float z3 = z0 - 1.0f + G3 * 3.0f; uint8_t ii = int32_t(i); uint8_t jj = int32_t(j); uint8_t kk = int32_t(k); uint8_t gi0 = perm[ii + perm[jj + perm[kk ] ] ] % 12; uint8_t gi1 = perm[ii + perm[jj + perm[kk + k1] + j1] + i1] % 12; uint8_t gi2 = perm[ii + perm[jj + perm[kk + k2] + j2] + i2] % 12; uint8_t gi3 = perm[ii + perm[jj + perm[kk + 1 ] + 1 ] + 1 ] % 12; float t0 = 0.5f - x0 * x0 - y0 * y0 - z0 * z0; float t1 = 0.5f - x1 * x1 - y1 * y1 - z1 * z1; float t2 = 0.5f - x2 * x2 - y2 * y2 - z2 * z2; float t3 = 0.5f - x3 * x3 - y3 * y3 - z3 * z3; float n0 = (t0 < 0) ? 0.0f : t0*t0*t0*t0 * dot(grad3[gi0], x0, y0, z0); float n1 = (t1 < 0) ? 0.0f : t1*t1*t1*t1 * dot(grad3[gi1], x1, y1, z1); float n2 = (t2 < 0) ? 0.0f : t2*t2*t2*t2 * dot(grad3[gi2], x2, y2, z2); float n3 = (t3 < 0) ? 0.0f : t3*t3*t3*t3 * dot(grad3[gi3], x3, y3, z3); return 32.0f * (n0 + n1 + n2 + n3); }