diff --git a/include/FastNoise/Generators/Cellular.h b/include/FastNoise/Generators/Cellular.h index c08a87b0..e52d2781 100644 --- a/include/FastNoise/Generators/Cellular.h +++ b/include/FastNoise/Generators/Cellular.h @@ -17,6 +17,7 @@ namespace FastNoise const float kJitter2D = 0.5f; const float kJitter3D = 0.45f; + const float kJitter4D = 0.45f; FASTNOISE_METADATA_ABSTRACT( Generator ) diff --git a/include/FastNoise/Generators/Cellular.inl b/include/FastNoise/Generators/Cellular.inl index d887332f..7507430d 100644 --- a/include/FastNoise/Generators/Cellular.inl +++ b/include/FastNoise/Generators/Cellular.inl @@ -120,6 +120,77 @@ public: return cellValue; } + + float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z , float32v w ) const final + { + float32v jitter = float32v( kJitter4D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z, w ); + float32v distance( FLT_MAX ); + float32v cellValue; + + int32v xc = FS_Convertf32_i32( x ) + int32v( -1 ); + int32v ycBase = FS_Convertf32_i32( y ) + int32v( -1 ); + int32v zcBase = FS_Convertf32_i32( z ) + int32v( -1 ); + int32v wcBase = FS_Convertf32_i32( w ) + int32v( -1 ); + + float32v xcf = FS_Converti32_f32( xc ) - x; + float32v ycfBase = FS_Converti32_f32( ycBase ) - y; + float32v zcfBase = FS_Converti32_f32( zcBase ) - z; + float32v wcfBase = FS_Converti32_f32( wcBase ) - w; + + xc *= int32v( Primes::X ); + ycBase *= int32v( Primes::Y ); + zcBase *= int32v( Primes::Z ); + wcBase *= int32v( Primes::W ); + + for( int xi = 0; xi < 3; xi++ ) + { + float32v ycf = ycfBase; + int32v yc = ycBase; + for( int yi = 0; yi < 3; yi++ ) + { + float32v zcf = zcfBase; + int32v zc = zcBase; + for( int zi = 0; zi < 3; zi++ ) + { + float32v wcf = wcfBase; + int32v wc = wcBase; + for( int wi = 0; wi < 3; wi++ ) + { + int32v hash = HashPrimesHB( seed, xc, yc, zc, wc ); + float32v xd = FS_Converti32_f32( hash & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v yd = FS_Converti32_f32( (hash >> 8) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v zd = FS_Converti32_f32( (hash >> 16) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v wd = FS_Converti32_f32( (hash >> 24) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + + float32v invMag = jitter * FS_InvSqrt_f32( FS_FMulAdd_f32( xd, xd, FS_FMulAdd_f32( yd, yd, FS_FMulAdd_f32( zd, zd, wd * wd ) ) ) ); + xd = FS_FMulAdd_f32( xd, invMag, xcf ); + yd = FS_FMulAdd_f32( yd, invMag, ycf ); + zd = FS_FMulAdd_f32( zd, invMag, zcf ); + wd = FS_FMulAdd_f32( wd, invMag, wcf ); + + float32v newCellValue = float32v( (float)(1.0 / INT_MAX) ) * FS_Converti32_f32( hash ); + float32v newDistance = CalcDistance( mDistanceFunction, xd, yd, zd, wd ); + + mask32v closer = FS_LessThan_f32( newDistance, distance ); + + distance = FS_Min_f32( newDistance, distance ); + cellValue = FS_Select_f32( closer, newCellValue, cellValue ); + + wcf += float32v( 1 ); + wc += int32v( Primes::W ); + } + zcf += float32v( 1 ); + zc += int32v( Primes::Z ); + } + ycf += float32v( 1 ); + yc += int32v( Primes::Y ); + } + xcf += float32v( 1 ); + xc += int32v( Primes::X ); + } + + return cellValue; + } }; template @@ -130,7 +201,6 @@ public: { float32v jitter = float32v( kJitter2D ) * this->GetSourceValue( mJitterModifier, seed, x, y ); - int maxDistanceIndex = (mReturnType == ReturnType::Index0) ? mDistanceIndex0 : std::max( mDistanceIndex0, mDistanceIndex1 ); std::array distance; distance.fill( float32v( INFINITY ) ); @@ -159,7 +229,7 @@ public: float32v newDistance = CalcDistance( mDistanceFunction, xd, yd ); - for( int i = maxDistanceIndex; i > 0; i-- ) + for( int i = kMaxDistanceCount - 1; i > 0; i-- ) { distance[i] = FS_Max_f32( FS_Min_f32( distance[i], newDistance ), distance[i - 1] ); } @@ -180,7 +250,6 @@ public: { float32v jitter = float32v( kJitter3D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z ); - int maxDistanceIndex = (mReturnType == ReturnType::Index0) ? mDistanceIndex0 : std::max( mDistanceIndex0, mDistanceIndex1 ); std::array distance; distance.fill( float32v( INFINITY ) ); @@ -218,7 +287,7 @@ public: float32v newDistance = CalcDistance( mDistanceFunction, xd, yd, zd ); - for( int i = maxDistanceIndex; i > 0; i-- ) + for( int i = kMaxDistanceCount - 1; i > 0; i-- ) { distance[i] = FS_Max_f32( FS_Min_f32( distance[i], newDistance ), distance[i - 1] ); } @@ -238,6 +307,79 @@ public: return GetReturn( distance ); } + float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z, float32v w ) const final + { + float32v jitter = float32v( kJitter4D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z, w ); + + std::array distance; + distance.fill( float32v( INFINITY ) ); + + int32v xc = FS_Convertf32_i32( x ) + int32v( -1 ); + int32v ycBase = FS_Convertf32_i32( y ) + int32v( -1 ); + int32v zcBase = FS_Convertf32_i32( z ) + int32v( -1 ); + int32v wcBase = FS_Convertf32_i32( w ) + int32v( -1 ); + + float32v xcf = FS_Converti32_f32( xc ) - x; + float32v ycfBase = FS_Converti32_f32( ycBase ) - y; + float32v zcfBase = FS_Converti32_f32( zcBase ) - z; + float32v wcfBase = FS_Converti32_f32( wcBase ) - w; + + xc *= int32v( Primes::X ); + ycBase *= int32v( Primes::Y ); + zcBase *= int32v( Primes::Z ); + wcBase *= int32v( Primes::W ); + + for( int xi = 0; xi < 3; xi++ ) + { + float32v ycf = ycfBase; + int32v yc = ycBase; + for( int yi = 0; yi < 3; yi++ ) + { + float32v zcf = zcfBase; + int32v zc = zcBase; + for( int zi = 0; zi < 3; zi++ ) + { + float32v wcf = wcfBase; + int32v wc = wcBase; + for( int wi = 0; wi < 3; wi++ ) + { + int32v hash = HashPrimesHB( seed, xc, yc, zc, wc ); + float32v xd = FS_Converti32_f32( hash & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v yd = FS_Converti32_f32( (hash >> 8) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v zd = FS_Converti32_f32( (hash >> 16) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v wd = FS_Converti32_f32( (hash >> 24) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + + float32v invMag = jitter * FS_InvSqrt_f32( FS_FMulAdd_f32( xd, xd, FS_FMulAdd_f32( yd, yd, FS_FMulAdd_f32( zd, zd, wd * wd ) ) ) ); + xd = FS_FMulAdd_f32( xd, invMag, xcf ); + yd = FS_FMulAdd_f32( yd, invMag, ycf ); + zd = FS_FMulAdd_f32( zd, invMag, zcf ); + wd = FS_FMulAdd_f32( wd, invMag, wcf ); + + float32v newDistance = CalcDistance( mDistanceFunction, xd, yd, zd, wd ); + + for( int i = kMaxDistanceCount - 1; i > 0; i-- ) + { + distance[i] = FS_Max_f32( FS_Min_f32( distance[i], newDistance ), distance[i - 1] ); + } + + distance[0] = FS_Min_f32( distance[0], newDistance ); + + wcf += float32v( 1 ); + wc += int32v( Primes::W ); + } + zcf += float32v( 1 ); + zc += int32v( Primes::Z ); + } + ycf += float32v( 1 ); + yc += int32v( Primes::Y ); + } + xcf += float32v( 1 ); + xc += int32v( Primes::X ); + } + + return GetReturn( distance ); + } + protected: FS_INLINE float32v GetReturn( std::array& distance ) const { @@ -384,4 +526,79 @@ public: return this->GetSourceValue( mLookup, seed - int32v( -1 ), cellX * float32v( mLookupFreq ), cellY * float32v( mLookupFreq ), cellZ * float32v( mLookupFreq ) ); } + + + float32v FS_VECTORCALL Gen( int32v seed, float32v x, float32v y, float32v z, float32v w ) const final + { + float32v jitter = float32v( kJitter4D ) * this->GetSourceValue( mJitterModifier, seed, x, y, z, w ); + float32v distance( FLT_MAX ); + float32v cellX, cellY, cellZ, cellW; + + int32v xc = FS_Convertf32_i32( x ) + int32v( -1 ); + int32v ycBase = FS_Convertf32_i32( y ) + int32v( -1 ); + int32v zcBase = FS_Convertf32_i32( z ) + int32v( -1 ); + int32v wcBase = FS_Convertf32_i32( w ) + int32v( -1 ); + + float32v xcf = FS_Converti32_f32( xc ) - x; + float32v ycfBase = FS_Converti32_f32( ycBase ) - y; + float32v zcfBase = FS_Converti32_f32( zcBase ) - z; + float32v wcfBase = FS_Converti32_f32( wcBase ) - w; + + xc *= int32v( Primes::X ); + ycBase *= int32v( Primes::Y ); + zcBase *= int32v( Primes::Z ); + wcBase *= int32v( Primes::W ); + + for( int xi = 0; xi < 3; xi++ ) + { + float32v ycf = ycfBase; + int32v yc = ycBase; + for( int yi = 0; yi < 3; yi++ ) + { + float32v zcf = zcfBase; + int32v zc = zcBase; + for( int zi = 0; zi < 3; zi++ ) + { + float32v wcf = wcfBase; + int32v wc = wcBase; + for( int wi = 0; wi < 3; wi++ ) + { + int32v hash = HashPrimesHB( seed, xc, yc, zc, wc ); + float32v xd = FS_Converti32_f32( hash & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v yd = FS_Converti32_f32( (hash >> 8) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v zd = FS_Converti32_f32( (hash >> 16) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + float32v wd = FS_Converti32_f32( (hash >> 24) & int32v( 0xff ) ) - float32v( 0xff / 2.0f ); + + float32v invMag = jitter * FS_InvSqrt_f32( FS_FMulAdd_f32( xd, xd, FS_FMulAdd_f32( yd, yd, FS_FMulAdd_f32( zd, zd, wd * wd ) ) ) ); + xd = FS_FMulAdd_f32( xd, invMag, xcf ); + yd = FS_FMulAdd_f32( yd, invMag, ycf ); + zd = FS_FMulAdd_f32( zd, invMag, zcf ); + wd = FS_FMulAdd_f32( wd, invMag, wcf ); + + float32v newCellValue = float32v( (float)(1.0 / INT_MAX) ) * FS_Converti32_f32( hash ); + float32v newDistance = CalcDistance( mDistanceFunction, xd, yd, zd, wd ); + + mask32v closer = FS_LessThan_f32( newDistance, distance ); + distance = FS_Min_f32( newDistance, distance ); + + cellX = FS_Select_f32( closer, xd + x, cellX ); + cellY = FS_Select_f32( closer, yd + y, cellY ); + cellZ = FS_Select_f32( closer, zd + z, cellZ ); + cellW = FS_Select_f32( closer, wd + w, cellW ); + + wcf += float32v( 1 ); + wc += int32v( Primes::W ); + } + zcf += float32v( 1 ); + zc += int32v( Primes::Z ); + } + ycf += float32v( 1 ); + yc += int32v( Primes::Y ); + } + xcf += float32v( 1 ); + xc += int32v( Primes::X ); + } + + return this->GetSourceValue( mLookup, seed - int32v( -1 ), cellX * float32v( mLookupFreq ), cellY * float32v( mLookupFreq ), cellZ * float32v( mLookupFreq ), cellW * float32v( mLookupFreq ) ); + } };