├── .gitignore ├── FastNoise.cs ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | 254 | *.sln 255 | *.csproj 256 | *.config 257 | /Properties 258 | Program.cs 259 | /LibNoise 260 | /FastNoiseOLD.cs 261 | /OpenSimplexNoise.cs 262 | -------------------------------------------------------------------------------- /FastNoise.cs: -------------------------------------------------------------------------------- 1 | // FastNoise.cs 2 | // 3 | // MIT License 4 | // 5 | // Copyright(c) 2017 Jordan Peck 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files(the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions : 13 | // 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | // 25 | // The developer's email is jorzixdan.me2@gzixmail.com (for great email, take 26 | // off every 'zix'.) 27 | // 28 | 29 | // Uncomment the line below to swap all the inputs/outputs/calculations of FastNoise to doubles instead of floats 30 | //#define FN_USE_DOUBLES 31 | 32 | #if FN_USE_DOUBLES 33 | using FN_DECIMAL = System.Double; 34 | #else 35 | using FN_DECIMAL = System.Single; 36 | #endif 37 | 38 | using System; 39 | using System.Runtime.CompilerServices; 40 | 41 | public class FastNoise 42 | { 43 | private const Int16 FN_INLINE = 256; //(Int16)MethodImplOptions.AggressiveInlining; 44 | private const int FN_CELLULAR_INDEX_MAX = 3; 45 | 46 | public enum NoiseType { Value, ValueFractal, Perlin, PerlinFractal, Simplex, SimplexFractal, Cellular, WhiteNoise, Cubic, CubicFractal }; 47 | public enum Interp { Linear, Hermite, Quintic }; 48 | public enum FractalType { FBM, Billow, RigidMulti }; 49 | public enum CellularDistanceFunction { Euclidean, Manhattan, Natural }; 50 | public enum CellularReturnType { CellValue, NoiseLookup, Distance, Distance2, Distance2Add, Distance2Sub, Distance2Mul, Distance2Div }; 51 | 52 | private int m_seed = 1337; 53 | private FN_DECIMAL m_frequency = (FN_DECIMAL)0.01; 54 | private Interp m_interp = Interp.Quintic; 55 | private NoiseType m_noiseType = NoiseType.Simplex; 56 | 57 | private int m_octaves = 3; 58 | private FN_DECIMAL m_lacunarity = (FN_DECIMAL)2.0; 59 | private FN_DECIMAL m_gain = (FN_DECIMAL)0.5; 60 | private FractalType m_fractalType = FractalType.FBM; 61 | 62 | private FN_DECIMAL m_fractalBounding; 63 | 64 | private CellularDistanceFunction m_cellularDistanceFunction = CellularDistanceFunction.Euclidean; 65 | private CellularReturnType m_cellularReturnType = CellularReturnType.CellValue; 66 | private FastNoise m_cellularNoiseLookup = null; 67 | private int m_cellularDistanceIndex0 = 0; 68 | private int m_cellularDistanceIndex1 = 1; 69 | private float m_cellularJitter = 0.45f; 70 | 71 | private FN_DECIMAL m_gradientPerturbAmp = (FN_DECIMAL)1.0; 72 | 73 | public FastNoise(int seed = 1337) 74 | { 75 | m_seed = seed; 76 | CalculateFractalBounding(); 77 | } 78 | 79 | // Returns a 0 float/double 80 | public static FN_DECIMAL GetDecimalType() { return 0; } 81 | 82 | // Returns the seed used by this object 83 | public int GetSeed() { return m_seed; } 84 | 85 | // Sets seed used for all noise types 86 | // Default: 1337 87 | public void SetSeed(int seed) { m_seed = seed; } 88 | 89 | // Sets frequency for all noise types 90 | // Default: 0.01 91 | public void SetFrequency(FN_DECIMAL frequency) { m_frequency = frequency; } 92 | 93 | // Changes the interpolation method used to smooth between noise values 94 | // Possible interpolation methods (lowest to highest quality) : 95 | // - Linear 96 | // - Hermite 97 | // - Quintic 98 | // Used in Value, Gradient Noise and Position Perturbing 99 | // Default: Quintic 100 | public void SetInterp(Interp interp) { m_interp = interp; } 101 | 102 | // Sets noise return type of GetNoise(...) 103 | // Default: Simplex 104 | public void SetNoiseType(NoiseType noiseType) { m_noiseType = noiseType; } 105 | 106 | 107 | // Sets octave count for all fractal noise types 108 | // Default: 3 109 | public void SetFractalOctaves(int octaves) { m_octaves = octaves; CalculateFractalBounding(); } 110 | 111 | // Sets octave lacunarity for all fractal noise types 112 | // Default: 2.0 113 | public void SetFractalLacunarity(FN_DECIMAL lacunarity) { m_lacunarity = lacunarity; } 114 | 115 | // Sets octave gain for all fractal noise types 116 | // Default: 0.5 117 | public void SetFractalGain(FN_DECIMAL gain) { m_gain = gain; CalculateFractalBounding(); } 118 | 119 | // Sets method for combining octaves in all fractal noise types 120 | // Default: FBM 121 | public void SetFractalType(FractalType fractalType) { m_fractalType = fractalType; } 122 | 123 | 124 | // Sets return type from cellular noise calculations 125 | // Note: NoiseLookup requires another FastNoise object be set with SetCellularNoiseLookup() to function 126 | // Default: CellValue 127 | public void SetCellularDistanceFunction(CellularDistanceFunction cellularDistanceFunction) { m_cellularDistanceFunction = cellularDistanceFunction; } 128 | 129 | // Sets distance function used in cellular noise calculations 130 | // Default: Euclidean 131 | public void SetCellularReturnType(CellularReturnType cellularReturnType) { m_cellularReturnType = cellularReturnType; } 132 | 133 | // Sets the 2 distance indicies used for distance2 return types 134 | // Default: 0, 1 135 | // Note: index0 should be lower than index1 136 | // Both indicies must be >= 0, index1 must be < 4 137 | public void SetCellularDistance2Indicies(int cellularDistanceIndex0, int cellularDistanceIndex1) 138 | { 139 | m_cellularDistanceIndex0 = Math.Min(cellularDistanceIndex0, cellularDistanceIndex1); 140 | m_cellularDistanceIndex1 = Math.Max(cellularDistanceIndex0, cellularDistanceIndex1); 141 | 142 | m_cellularDistanceIndex0 = Math.Min(Math.Max(m_cellularDistanceIndex0, 0), FN_CELLULAR_INDEX_MAX); 143 | m_cellularDistanceIndex1 = Math.Min(Math.Max(m_cellularDistanceIndex1, 0), FN_CELLULAR_INDEX_MAX); 144 | } 145 | 146 | // Sets the maximum distance a cellular point can move from it's grid position 147 | // Setting this high will make artifacts more common 148 | // Default: 0.45 149 | public void SetCellularJitter(float cellularJitter) { m_cellularJitter = cellularJitter; } 150 | 151 | // Noise used to calculate a cell value if cellular return type is NoiseLookup 152 | // The lookup value is acquired through GetNoise() so ensure you SetNoiseType() on the noise lookup, value, gradient or simplex is recommended 153 | public void SetCellularNoiseLookup(FastNoise noise) { m_cellularNoiseLookup = noise; } 154 | 155 | 156 | // Sets the maximum perturb distance from original location when using GradientPerturb{Fractal}(...) 157 | // Default: 1.0 158 | public void SetGradientPerturbAmp(FN_DECIMAL gradientPerturbAmp) { m_gradientPerturbAmp = gradientPerturbAmp; } 159 | 160 | private struct Float2 161 | { 162 | public readonly FN_DECIMAL x, y; 163 | public Float2(FN_DECIMAL x, FN_DECIMAL y) 164 | { 165 | this.x = x; 166 | this.y = y; 167 | } 168 | } 169 | 170 | private struct Float3 171 | { 172 | public readonly FN_DECIMAL x, y, z; 173 | public Float3(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 174 | { 175 | this.x = x; 176 | this.y = y; 177 | this.z = z; 178 | } 179 | } 180 | 181 | private static readonly Float2[] GRAD_2D = { 182 | new Float2(-1,-1), new Float2( 1,-1), new Float2(-1, 1), new Float2( 1, 1), 183 | new Float2( 0,-1), new Float2(-1, 0), new Float2( 0, 1), new Float2( 1, 0), 184 | }; 185 | 186 | private static readonly Float3[] GRAD_3D = { 187 | new Float3( 1, 1, 0), new Float3(-1, 1, 0), new Float3( 1,-1, 0), new Float3(-1,-1, 0), 188 | new Float3( 1, 0, 1), new Float3(-1, 0, 1), new Float3( 1, 0,-1), new Float3(-1, 0,-1), 189 | new Float3( 0, 1, 1), new Float3( 0,-1, 1), new Float3( 0, 1,-1), new Float3( 0,-1,-1), 190 | new Float3( 1, 1, 0), new Float3( 0,-1, 1), new Float3(-1, 1, 0), new Float3( 0,-1,-1), 191 | }; 192 | 193 | private static readonly Float2[] CELL_2D = 194 | { 195 | new Float2(-0.2700222198f, -0.9628540911f), new Float2(0.3863092627f, -0.9223693152f), new Float2(0.04444859006f, -0.999011673f), new Float2(-0.5992523158f, -0.8005602176f), new Float2(-0.7819280288f, 0.6233687174f), new Float2(0.9464672271f, 0.3227999196f), new Float2(-0.6514146797f, -0.7587218957f), new Float2(0.9378472289f, 0.347048376f), 196 | new Float2(-0.8497875957f, -0.5271252623f), new Float2(-0.879042592f, 0.4767432447f), new Float2(-0.892300288f, -0.4514423508f), new Float2(-0.379844434f, -0.9250503802f), new Float2(-0.9951650832f, 0.0982163789f), new Float2(0.7724397808f, -0.6350880136f), new Float2(0.7573283322f, -0.6530343002f), new Float2(-0.9928004525f, -0.119780055f), 197 | new Float2(-0.0532665713f, 0.9985803285f), new Float2(0.9754253726f, -0.2203300762f), new Float2(-0.7665018163f, 0.6422421394f), new Float2(0.991636706f, 0.1290606184f), new Float2(-0.994696838f, 0.1028503788f), new Float2(-0.5379205513f, -0.84299554f), new Float2(0.5022815471f, -0.8647041387f), new Float2(0.4559821461f, -0.8899889226f), 198 | new Float2(-0.8659131224f, -0.5001944266f), new Float2(0.0879458407f, -0.9961252577f), new Float2(-0.5051684983f, 0.8630207346f), new Float2(0.7753185226f, -0.6315704146f), new Float2(-0.6921944612f, 0.7217110418f), new Float2(-0.5191659449f, -0.8546734591f), new Float2(0.8978622882f, -0.4402764035f), new Float2(-0.1706774107f, 0.9853269617f), 199 | new Float2(-0.9353430106f, -0.3537420705f), new Float2(-0.9992404798f, 0.03896746794f), new Float2(-0.2882064021f, -0.9575683108f), new Float2(-0.9663811329f, 0.2571137995f), new Float2(-0.8759714238f, -0.4823630009f), new Float2(-0.8303123018f, -0.5572983775f), new Float2(0.05110133755f, -0.9986934731f), new Float2(-0.8558373281f, -0.5172450752f), 200 | new Float2(0.09887025282f, 0.9951003332f), new Float2(0.9189016087f, 0.3944867976f), new Float2(-0.2439375892f, -0.9697909324f), new Float2(-0.8121409387f, -0.5834613061f), new Float2(-0.9910431363f, 0.1335421355f), new Float2(0.8492423985f, -0.5280031709f), new Float2(-0.9717838994f, -0.2358729591f), new Float2(0.9949457207f, 0.1004142068f), 201 | new Float2(0.6241065508f, -0.7813392434f), new Float2(0.662910307f, 0.7486988212f), new Float2(-0.7197418176f, 0.6942418282f), new Float2(-0.8143370775f, -0.5803922158f), new Float2(0.104521054f, -0.9945226741f), new Float2(-0.1065926113f, -0.9943027784f), new Float2(0.445799684f, -0.8951327509f), new Float2(0.105547406f, 0.9944142724f), 202 | new Float2(-0.992790267f, 0.1198644477f), new Float2(-0.8334366408f, 0.552615025f), new Float2(0.9115561563f, -0.4111755999f), new Float2(0.8285544909f, -0.5599084351f), new Float2(0.7217097654f, -0.6921957921f), new Float2(0.4940492677f, -0.8694339084f), new Float2(-0.3652321272f, -0.9309164803f), new Float2(-0.9696606758f, 0.2444548501f), 203 | new Float2(0.08925509731f, -0.996008799f), new Float2(0.5354071276f, -0.8445941083f), new Float2(-0.1053576186f, 0.9944343981f), new Float2(-0.9890284586f, 0.1477251101f), new Float2(0.004856104961f, 0.9999882091f), new Float2(0.9885598478f, 0.1508291331f), new Float2(0.9286129562f, -0.3710498316f), new Float2(-0.5832393863f, -0.8123003252f), 204 | new Float2(0.3015207509f, 0.9534596146f), new Float2(-0.9575110528f, 0.2883965738f), new Float2(0.9715802154f, -0.2367105511f), new Float2(0.229981792f, 0.9731949318f), new Float2(0.955763816f, -0.2941352207f), new Float2(0.740956116f, 0.6715534485f), new Float2(-0.9971513787f, -0.07542630764f), new Float2(0.6905710663f, -0.7232645452f), 205 | new Float2(-0.290713703f, -0.9568100872f), new Float2(0.5912777791f, -0.8064679708f), new Float2(-0.9454592212f, -0.325740481f), new Float2(0.6664455681f, 0.74555369f), new Float2(0.6236134912f, 0.7817328275f), new Float2(0.9126993851f, -0.4086316587f), new Float2(-0.8191762011f, 0.5735419353f), new Float2(-0.8812745759f, -0.4726046147f), 206 | new Float2(0.9953313627f, 0.09651672651f), new Float2(0.9855650846f, -0.1692969699f), new Float2(-0.8495980887f, 0.5274306472f), new Float2(0.6174853946f, -0.7865823463f), new Float2(0.8508156371f, 0.52546432f), new Float2(0.9985032451f, -0.05469249926f), new Float2(0.1971371563f, -0.9803759185f), new Float2(0.6607855748f, -0.7505747292f), 207 | new Float2(-0.03097494063f, 0.9995201614f), new Float2(-0.6731660801f, 0.739491331f), new Float2(-0.7195018362f, -0.6944905383f), new Float2(0.9727511689f, 0.2318515979f), new Float2(0.9997059088f, -0.0242506907f), new Float2(0.4421787429f, -0.8969269532f), new Float2(0.9981350961f, -0.061043673f), new Float2(-0.9173660799f, -0.3980445648f), 208 | new Float2(-0.8150056635f, -0.5794529907f), new Float2(-0.8789331304f, 0.4769450202f), new Float2(0.0158605829f, 0.999874213f), new Float2(-0.8095464474f, 0.5870558317f), new Float2(-0.9165898907f, -0.3998286786f), new Float2(-0.8023542565f, 0.5968480938f), new Float2(-0.5176737917f, 0.8555780767f), new Float2(-0.8154407307f, -0.5788405779f), 209 | new Float2(0.4022010347f, -0.9155513791f), new Float2(-0.9052556868f, -0.4248672045f), new Float2(0.7317445619f, 0.6815789728f), new Float2(-0.5647632201f, -0.8252529947f), new Float2(-0.8403276335f, -0.5420788397f), new Float2(-0.9314281527f, 0.363925262f), new Float2(0.5238198472f, 0.8518290719f), new Float2(0.7432803869f, -0.6689800195f), 210 | new Float2(-0.985371561f, -0.1704197369f), new Float2(0.4601468731f, 0.88784281f), new Float2(0.825855404f, 0.5638819483f), new Float2(0.6182366099f, 0.7859920446f), new Float2(0.8331502863f, -0.553046653f), new Float2(0.1500307506f, 0.9886813308f), new Float2(-0.662330369f, -0.7492119075f), new Float2(-0.668598664f, 0.743623444f), 211 | new Float2(0.7025606278f, 0.7116238924f), new Float2(-0.5419389763f, -0.8404178401f), new Float2(-0.3388616456f, 0.9408362159f), new Float2(0.8331530315f, 0.5530425174f), new Float2(-0.2989720662f, -0.9542618632f), new Float2(0.2638522993f, 0.9645630949f), new Float2(0.124108739f, -0.9922686234f), new Float2(-0.7282649308f, -0.6852956957f), 212 | new Float2(0.6962500149f, 0.7177993569f), new Float2(-0.9183535368f, 0.3957610156f), new Float2(-0.6326102274f, -0.7744703352f), new Float2(-0.9331891859f, -0.359385508f), new Float2(-0.1153779357f, -0.9933216659f), new Float2(0.9514974788f, -0.3076565421f), new Float2(-0.08987977445f, -0.9959526224f), new Float2(0.6678496916f, 0.7442961705f), 213 | new Float2(0.7952400393f, -0.6062947138f), new Float2(-0.6462007402f, -0.7631674805f), new Float2(-0.2733598753f, 0.9619118351f), new Float2(0.9669590226f, -0.254931851f), new Float2(-0.9792894595f, 0.2024651934f), new Float2(-0.5369502995f, -0.8436138784f), new Float2(-0.270036471f, -0.9628500944f), new Float2(-0.6400277131f, 0.7683518247f), 214 | new Float2(-0.7854537493f, -0.6189203566f), new Float2(0.06005905383f, -0.9981948257f), new Float2(-0.02455770378f, 0.9996984141f), new Float2(-0.65983623f, 0.751409442f), new Float2(-0.6253894466f, -0.7803127835f), new Float2(-0.6210408851f, -0.7837781695f), new Float2(0.8348888491f, 0.5504185768f), new Float2(-0.1592275245f, 0.9872419133f), 215 | new Float2(0.8367622488f, 0.5475663786f), new Float2(-0.8675753916f, -0.4973056806f), new Float2(-0.2022662628f, -0.9793305667f), new Float2(0.9399189937f, 0.3413975472f), new Float2(0.9877404807f, -0.1561049093f), new Float2(-0.9034455656f, 0.4287028224f), new Float2(0.1269804218f, -0.9919052235f), new Float2(-0.3819600854f, 0.924178821f), 216 | new Float2(0.9754625894f, 0.2201652486f), new Float2(-0.3204015856f, -0.9472818081f), new Float2(-0.9874760884f, 0.1577687387f), new Float2(0.02535348474f, -0.9996785487f), new Float2(0.4835130794f, -0.8753371362f), new Float2(-0.2850799925f, -0.9585037287f), new Float2(-0.06805516006f, -0.99768156f), new Float2(-0.7885244045f, -0.6150034663f), 217 | new Float2(0.3185392127f, -0.9479096845f), new Float2(0.8880043089f, 0.4598351306f), new Float2(0.6476921488f, -0.7619021462f), new Float2(0.9820241299f, 0.1887554194f), new Float2(0.9357275128f, -0.3527237187f), new Float2(-0.8894895414f, 0.4569555293f), new Float2(0.7922791302f, 0.6101588153f), new Float2(0.7483818261f, 0.6632681526f), 218 | new Float2(-0.7288929755f, -0.6846276581f), new Float2(0.8729032783f, -0.4878932944f), new Float2(0.8288345784f, 0.5594937369f), new Float2(0.08074567077f, 0.9967347374f), new Float2(0.9799148216f, -0.1994165048f), new Float2(-0.580730673f, -0.8140957471f), new Float2(-0.4700049791f, -0.8826637636f), new Float2(0.2409492979f, 0.9705377045f), 219 | new Float2(0.9437816757f, -0.3305694308f), new Float2(-0.8927998638f, -0.4504535528f), new Float2(-0.8069622304f, 0.5906030467f), new Float2(0.06258973166f, 0.9980393407f), new Float2(-0.9312597469f, 0.3643559849f), new Float2(0.5777449785f, 0.8162173362f), new Float2(-0.3360095855f, -0.941858566f), new Float2(0.697932075f, -0.7161639607f), 220 | new Float2(-0.002008157227f, -0.9999979837f), new Float2(-0.1827294312f, -0.9831632392f), new Float2(-0.6523911722f, 0.7578824173f), new Float2(-0.4302626911f, -0.9027037258f), new Float2(-0.9985126289f, -0.05452091251f), new Float2(-0.01028102172f, -0.9999471489f), new Float2(-0.4946071129f, 0.8691166802f), new Float2(-0.2999350194f, 0.9539596344f), 221 | new Float2(0.8165471961f, 0.5772786819f), new Float2(0.2697460475f, 0.962931498f), new Float2(-0.7306287391f, -0.6827749597f), new Float2(-0.7590952064f, -0.6509796216f), new Float2(-0.907053853f, 0.4210146171f), new Float2(-0.5104861064f, -0.8598860013f), new Float2(0.8613350597f, 0.5080373165f), new Float2(0.5007881595f, -0.8655698812f), 222 | new Float2(-0.654158152f, 0.7563577938f), new Float2(-0.8382755311f, -0.545246856f), new Float2(0.6940070834f, 0.7199681717f), new Float2(0.06950936031f, 0.9975812994f), new Float2(0.1702942185f, -0.9853932612f), new Float2(0.2695973274f, 0.9629731466f), new Float2(0.5519612192f, -0.8338697815f), new Float2(0.225657487f, -0.9742067022f), 223 | new Float2(0.4215262855f, -0.9068161835f), new Float2(0.4881873305f, -0.8727388672f), new Float2(-0.3683854996f, -0.9296731273f), new Float2(-0.9825390578f, 0.1860564427f), new Float2(0.81256471f, 0.5828709909f), new Float2(0.3196460933f, -0.9475370046f), new Float2(0.9570913859f, 0.2897862643f), new Float2(-0.6876655497f, -0.7260276109f), 224 | new Float2(-0.9988770922f, -0.047376731f), new Float2(-0.1250179027f, 0.992154486f), new Float2(-0.8280133617f, 0.560708367f), new Float2(0.9324863769f, -0.3612051451f), new Float2(0.6394653183f, 0.7688199442f), new Float2(-0.01623847064f, -0.9998681473f), new Float2(-0.9955014666f, -0.09474613458f), new Float2(-0.81453315f, 0.580117012f), 225 | new Float2(0.4037327978f, -0.9148769469f), new Float2(0.9944263371f, 0.1054336766f), new Float2(-0.1624711654f, 0.9867132919f), new Float2(-0.9949487814f, -0.100383875f), new Float2(-0.6995302564f, 0.7146029809f), new Float2(0.5263414922f, -0.85027327f), new Float2(-0.5395221479f, 0.841971408f), new Float2(0.6579370318f, 0.7530729462f), 226 | new Float2(0.01426758847f, -0.9998982128f), new Float2(-0.6734383991f, 0.7392433447f), new Float2(0.639412098f, -0.7688642071f), new Float2(0.9211571421f, 0.3891908523f), new Float2(-0.146637214f, -0.9891903394f), new Float2(-0.782318098f, 0.6228791163f), new Float2(-0.5039610839f, -0.8637263605f), new Float2(-0.7743120191f, -0.6328039957f), 227 | }; 228 | 229 | private static readonly Float3[] CELL_3D = 230 | { 231 | new Float3(-0.7292736885f, -0.6618439697f, 0.1735581948f), new Float3(0.790292081f, -0.5480887466f, -0.2739291014f), new Float3(0.7217578935f, 0.6226212466f, -0.3023380997f), new Float3(0.565683137f, -0.8208298145f, -0.0790000257f), new Float3(0.760049034f, -0.5555979497f, -0.3370999617f), new Float3(0.3713945616f, 0.5011264475f, 0.7816254623f), new Float3(-0.1277062463f, -0.4254438999f, -0.8959289049f), new Float3(-0.2881560924f, -0.5815838982f, 0.7607405838f), 232 | new Float3(0.5849561111f, -0.662820239f, -0.4674352136f), new Float3(0.3307171178f, 0.0391653737f, 0.94291689f), new Float3(0.8712121778f, -0.4113374369f, -0.2679381538f), new Float3(0.580981015f, 0.7021915846f, 0.4115677815f), new Float3(0.503756873f, 0.6330056931f, -0.5878203852f), new Float3(0.4493712205f, 0.601390195f, 0.6606022552f), new Float3(-0.6878403724f, 0.09018890807f, -0.7202371714f), new Float3(-0.5958956522f, -0.6469350577f, 0.475797649f), 233 | new Float3(-0.5127052122f, 0.1946921978f, -0.8361987284f), new Float3(-0.9911507142f, -0.05410276466f, -0.1212153153f), new Float3(-0.2149721042f, 0.9720882117f, -0.09397607749f), new Float3(-0.7518650936f, -0.5428057603f, 0.3742469607f), new Float3(0.5237068895f, 0.8516377189f, -0.02107817834f), new Float3(0.6333504779f, 0.1926167129f, -0.7495104896f), new Float3(-0.06788241606f, 0.3998305789f, 0.9140719259f), new Float3(-0.5538628599f, -0.4729896695f, -0.6852128902f), 234 | new Float3(-0.7261455366f, -0.5911990757f, 0.3509933228f), new Float3(-0.9229274737f, -0.1782808786f, 0.3412049336f), new Float3(-0.6968815002f, 0.6511274338f, 0.3006480328f), new Float3(0.9608044783f, -0.2098363234f, -0.1811724921f), new Float3(0.06817146062f, -0.9743405129f, 0.2145069156f), new Float3(-0.3577285196f, -0.6697087264f, -0.6507845481f), new Float3(-0.1868621131f, 0.7648617052f, -0.6164974636f), new Float3(-0.6541697588f, 0.3967914832f, 0.6439087246f), 235 | new Float3(0.6993340405f, -0.6164538506f, 0.3618239211f), new Float3(-0.1546665739f, 0.6291283928f, 0.7617583057f), new Float3(-0.6841612949f, -0.2580482182f, -0.6821542638f), new Float3(0.5383980957f, 0.4258654885f, 0.7271630328f), new Float3(-0.5026987823f, -0.7939832935f, -0.3418836993f), new Float3(0.3202971715f, 0.2834415347f, 0.9039195862f), new Float3(0.8683227101f, -0.0003762656404f, -0.4959995258f), new Float3(0.791120031f, -0.08511045745f, 0.6057105799f), 236 | new Float3(-0.04011016052f, -0.4397248749f, 0.8972364289f), new Float3(0.9145119872f, 0.3579346169f, -0.1885487608f), new Float3(-0.9612039066f, -0.2756484276f, 0.01024666929f), new Float3(0.6510361721f, -0.2877799159f, -0.7023778346f), new Float3(-0.2041786351f, 0.7365237271f, 0.644859585f), new Float3(-0.7718263711f, 0.3790626912f, 0.5104855816f), new Float3(-0.3060082741f, -0.7692987727f, 0.5608371729f), new Float3(0.454007341f, -0.5024843065f, 0.7357899537f), 237 | new Float3(0.4816795475f, 0.6021208291f, -0.6367380315f), new Float3(0.6961980369f, -0.3222197429f, 0.641469197f), new Float3(-0.6532160499f, -0.6781148932f, 0.3368515753f), new Float3(0.5089301236f, -0.6154662304f, -0.6018234363f), new Float3(-0.1635919754f, -0.9133604627f, -0.372840892f), new Float3(0.52408019f, -0.8437664109f, 0.1157505864f), new Float3(0.5902587356f, 0.4983817807f, -0.6349883666f), new Float3(0.5863227872f, 0.494764745f, 0.6414307729f), 238 | new Float3(0.6779335087f, 0.2341345225f, 0.6968408593f), new Float3(0.7177054546f, -0.6858979348f, 0.120178631f), new Float3(-0.5328819713f, -0.5205125012f, 0.6671608058f), new Float3(-0.8654874251f, -0.0700727088f, -0.4960053754f), new Float3(-0.2861810166f, 0.7952089234f, 0.5345495242f), new Float3(-0.04849529634f, 0.9810836427f, -0.1874115585f), new Float3(-0.6358521667f, 0.6058348682f, 0.4781800233f), new Float3(0.6254794696f, -0.2861619734f, 0.7258696564f), 239 | new Float3(-0.2585259868f, 0.5061949264f, -0.8227581726f), new Float3(0.02136306781f, 0.5064016808f, -0.8620330371f), new Float3(0.200111773f, 0.8599263484f, 0.4695550591f), new Float3(0.4743561372f, 0.6014985084f, -0.6427953014f), new Float3(0.6622993731f, -0.5202474575f, -0.5391679918f), new Float3(0.08084972818f, -0.6532720452f, 0.7527940996f), new Float3(-0.6893687501f, 0.0592860349f, 0.7219805347f), new Float3(-0.1121887082f, -0.9673185067f, 0.2273952515f), 240 | new Float3(0.7344116094f, 0.5979668656f, -0.3210532909f), new Float3(0.5789393465f, -0.2488849713f, 0.7764570201f), new Float3(0.6988182827f, 0.3557169806f, -0.6205791146f), new Float3(-0.8636845529f, -0.2748771249f, -0.4224826141f), new Float3(-0.4247027957f, -0.4640880967f, 0.777335046f), new Float3(0.5257722489f, -0.8427017621f, 0.1158329937f), new Float3(0.9343830603f, 0.316302472f, -0.1639543925f), new Float3(-0.1016836419f, -0.8057303073f, -0.5834887393f), 241 | new Float3(-0.6529238969f, 0.50602126f, -0.5635892736f), new Float3(-0.2465286165f, -0.9668205684f, -0.06694497494f), new Float3(-0.9776897119f, -0.2099250524f, -0.007368825344f), new Float3(0.7736893337f, 0.5734244712f, 0.2694238123f), new Float3(-0.6095087895f, 0.4995678998f, 0.6155736747f), new Float3(0.5794535482f, 0.7434546771f, 0.3339292269f), new Float3(-0.8226211154f, 0.08142581855f, 0.5627293636f), new Float3(-0.510385483f, 0.4703667658f, 0.7199039967f), 242 | new Float3(-0.5764971849f, -0.07231656274f, -0.8138926898f), new Float3(0.7250628871f, 0.3949971505f, -0.5641463116f), new Float3(-0.1525424005f, 0.4860840828f, -0.8604958341f), new Float3(-0.5550976208f, -0.4957820792f, 0.667882296f), new Float3(-0.1883614327f, 0.9145869398f, 0.357841725f), new Float3(0.7625556724f, -0.5414408243f, -0.3540489801f), new Float3(-0.5870231946f, -0.3226498013f, -0.7424963803f), new Float3(0.3051124198f, 0.2262544068f, -0.9250488391f), 243 | new Float3(0.6379576059f, 0.577242424f, -0.5097070502f), new Float3(-0.5966775796f, 0.1454852398f, -0.7891830656f), new Float3(-0.658330573f, 0.6555487542f, -0.3699414651f), new Float3(0.7434892426f, 0.2351084581f, 0.6260573129f), new Float3(0.5562114096f, 0.8264360377f, -0.0873632843f), new Float3(-0.3028940016f, -0.8251527185f, 0.4768419182f), new Float3(0.1129343818f, -0.985888439f, -0.1235710781f), new Float3(0.5937652891f, -0.5896813806f, 0.5474656618f), 244 | new Float3(0.6757964092f, -0.5835758614f, -0.4502648413f), new Float3(0.7242302609f, -0.1152719764f, 0.6798550586f), new Float3(-0.9511914166f, 0.0753623979f, -0.2992580792f), new Float3(0.2539470961f, -0.1886339355f, 0.9486454084f), new Float3(0.571433621f, -0.1679450851f, -0.8032795685f), new Float3(-0.06778234979f, 0.3978269256f, 0.9149531629f), new Float3(0.6074972649f, 0.733060024f, -0.3058922593f), new Float3(-0.5435478392f, 0.1675822484f, 0.8224791405f), 245 | new Float3(-0.5876678086f, -0.3380045064f, -0.7351186982f), new Float3(-0.7967562402f, 0.04097822706f, -0.6029098428f), new Float3(-0.1996350917f, 0.8706294745f, 0.4496111079f), new Float3(-0.02787660336f, -0.9106232682f, -0.4122962022f), new Float3(-0.7797625996f, -0.6257634692f, 0.01975775581f), new Float3(-0.5211232846f, 0.7401644346f, -0.4249554471f), new Float3(0.8575424857f, 0.4053272873f, -0.3167501783f), new Float3(0.1045223322f, 0.8390195772f, -0.5339674439f), 246 | new Float3(0.3501822831f, 0.9242524096f, -0.1520850155f), new Float3(0.1987849858f, 0.07647613266f, 0.9770547224f), new Float3(0.7845996363f, 0.6066256811f, -0.1280964233f), new Float3(0.09006737436f, -0.9750989929f, -0.2026569073f), new Float3(-0.8274343547f, -0.542299559f, 0.1458203587f), new Float3(-0.3485797732f, -0.415802277f, 0.840000362f), new Float3(-0.2471778936f, -0.7304819962f, -0.6366310879f), new Float3(-0.3700154943f, 0.8577948156f, 0.3567584454f), 247 | new Float3(0.5913394901f, -0.548311967f, -0.5913303597f), new Float3(0.1204873514f, -0.7626472379f, -0.6354935001f), new Float3(0.616959265f, 0.03079647928f, 0.7863922953f), new Float3(0.1258156836f, -0.6640829889f, -0.7369967419f), new Float3(-0.6477565124f, -0.1740147258f, -0.7417077429f), new Float3(0.6217889313f, -0.7804430448f, -0.06547655076f), new Float3(0.6589943422f, -0.6096987708f, 0.4404473475f), new Float3(-0.2689837504f, -0.6732403169f, -0.6887635427f), 248 | new Float3(-0.3849775103f, 0.5676542638f, 0.7277093879f), new Float3(0.5754444408f, 0.8110471154f, -0.1051963504f), new Float3(0.9141593684f, 0.3832947817f, 0.131900567f), new Float3(-0.107925319f, 0.9245493968f, 0.3654593525f), new Float3(0.377977089f, 0.3043148782f, 0.8743716458f), new Float3(-0.2142885215f, -0.8259286236f, 0.5214617324f), new Float3(0.5802544474f, 0.4148098596f, -0.7008834116f), new Float3(-0.1982660881f, 0.8567161266f, -0.4761596756f), 249 | new Float3(-0.03381553704f, 0.3773180787f, -0.9254661404f), new Float3(-0.6867922841f, -0.6656597827f, 0.2919133642f), new Float3(0.7731742607f, -0.2875793547f, -0.5652430251f), new Float3(-0.09655941928f, 0.9193708367f, -0.3813575004f), new Float3(0.2715702457f, -0.9577909544f, -0.09426605581f), new Float3(0.2451015704f, -0.6917998565f, -0.6792188003f), new Float3(0.977700782f, -0.1753855374f, 0.1155036542f), new Float3(-0.5224739938f, 0.8521606816f, 0.02903615945f), 250 | new Float3(-0.7734880599f, -0.5261292347f, 0.3534179531f), new Float3(-0.7134492443f, -0.269547243f, 0.6467878011f), new Float3(0.1644037271f, 0.5105846203f, -0.8439637196f), new Float3(0.6494635788f, 0.05585611296f, 0.7583384168f), new Float3(-0.4711970882f, 0.5017280509f, -0.7254255765f), new Float3(-0.6335764307f, -0.2381686273f, -0.7361091029f), new Float3(-0.9021533097f, -0.270947803f, -0.3357181763f), new Float3(-0.3793711033f, 0.872258117f, 0.3086152025f), 251 | new Float3(-0.6855598966f, -0.3250143309f, 0.6514394162f), new Float3(0.2900942212f, -0.7799057743f, -0.5546100667f), new Float3(-0.2098319339f, 0.85037073f, 0.4825351604f), new Float3(-0.4592603758f, 0.6598504336f, -0.5947077538f), new Float3(0.8715945488f, 0.09616365406f, -0.4807031248f), new Float3(-0.6776666319f, 0.7118504878f, -0.1844907016f), new Float3(0.7044377633f, 0.312427597f, 0.637304036f), new Float3(-0.7052318886f, -0.2401093292f, -0.6670798253f), 252 | new Float3(0.081921007f, -0.7207336136f, -0.6883545647f), new Float3(-0.6993680906f, -0.5875763221f, -0.4069869034f), new Float3(-0.1281454481f, 0.6419895885f, 0.7559286424f), new Float3(-0.6337388239f, -0.6785471501f, -0.3714146849f), new Float3(0.5565051903f, -0.2168887573f, -0.8020356851f), new Float3(-0.5791554484f, 0.7244372011f, -0.3738578718f), new Float3(0.1175779076f, -0.7096451073f, 0.6946792478f), new Float3(-0.6134619607f, 0.1323631078f, 0.7785527795f), 253 | new Float3(0.6984635305f, -0.02980516237f, -0.715024719f), new Float3(0.8318082963f, -0.3930171956f, 0.3919597455f), new Float3(0.1469576422f, 0.05541651717f, -0.9875892167f), new Float3(0.708868575f, -0.2690503865f, 0.6520101478f), new Float3(0.2726053183f, 0.67369766f, -0.68688995f), new Float3(-0.6591295371f, 0.3035458599f, -0.6880466294f), new Float3(0.4815131379f, -0.7528270071f, 0.4487723203f), new Float3(0.9430009463f, 0.1675647412f, -0.2875261255f), 254 | new Float3(0.434802957f, 0.7695304522f, -0.4677277752f), new Float3(0.3931996188f, 0.594473625f, 0.7014236729f), new Float3(0.7254336655f, -0.603925654f, 0.3301814672f), new Float3(0.7590235227f, -0.6506083235f, 0.02433313207f), new Float3(-0.8552768592f, -0.3430042733f, 0.3883935666f), new Float3(-0.6139746835f, 0.6981725247f, 0.3682257648f), new Float3(-0.7465905486f, -0.5752009504f, 0.3342849376f), new Float3(0.5730065677f, 0.810555537f, -0.1210916791f), 255 | new Float3(-0.9225877367f, -0.3475211012f, -0.167514036f), new Float3(-0.7105816789f, -0.4719692027f, -0.5218416899f), new Float3(-0.08564609717f, 0.3583001386f, 0.929669703f), new Float3(-0.8279697606f, -0.2043157126f, 0.5222271202f), new Float3(0.427944023f, 0.278165994f, 0.8599346446f), new Float3(0.5399079671f, -0.7857120652f, -0.3019204161f), new Float3(0.5678404253f, -0.5495413974f, -0.6128307303f), new Float3(-0.9896071041f, 0.1365639107f, -0.04503418428f), 256 | new Float3(-0.6154342638f, -0.6440875597f, 0.4543037336f), new Float3(0.1074204368f, -0.7946340692f, 0.5975094525f), new Float3(-0.3595449969f, -0.8885529948f, 0.28495784f), new Float3(-0.2180405296f, 0.1529888965f, 0.9638738118f), new Float3(-0.7277432317f, -0.6164050508f, -0.3007234646f), new Float3(0.7249729114f, -0.00669719484f, 0.6887448187f), new Float3(-0.5553659455f, -0.5336586252f, 0.6377908264f), new Float3(0.5137558015f, 0.7976208196f, -0.3160000073f), 257 | new Float3(-0.3794024848f, 0.9245608561f, -0.03522751494f), new Float3(0.8229248658f, 0.2745365933f, -0.4974176556f), new Float3(-0.5404114394f, 0.6091141441f, 0.5804613989f), new Float3(0.8036581901f, -0.2703029469f, 0.5301601931f), new Float3(0.6044318879f, 0.6832968393f, 0.4095943388f), new Float3(0.06389988817f, 0.9658208605f, -0.2512108074f), new Float3(0.1087113286f, 0.7402471173f, -0.6634877936f), new Float3(-0.713427712f, -0.6926784018f, 0.1059128479f), 258 | new Float3(0.6458897819f, -0.5724548511f, -0.5050958653f), new Float3(-0.6553931414f, 0.7381471625f, 0.159995615f), new Float3(0.3910961323f, 0.9188871375f, -0.05186755998f), new Float3(-0.4879022471f, -0.5904376907f, 0.6429111375f), new Float3(0.6014790094f, 0.7707441366f, -0.2101820095f), new Float3(-0.5677173047f, 0.7511360995f, 0.3368851762f), new Float3(0.7858573506f, 0.226674665f, 0.5753666838f), new Float3(-0.4520345543f, -0.604222686f, -0.6561857263f), 259 | new Float3(0.002272116345f, 0.4132844051f, -0.9105991643f), new Float3(-0.5815751419f, -0.5162925989f, 0.6286591339f), new Float3(-0.03703704785f, 0.8273785755f, 0.5604221175f), new Float3(-0.5119692504f, 0.7953543429f, -0.3244980058f), new Float3(-0.2682417366f, -0.9572290247f, -0.1084387619f), new Float3(-0.2322482736f, -0.9679131102f, -0.09594243324f), new Float3(0.3554328906f, -0.8881505545f, 0.2913006227f), new Float3(0.7346520519f, -0.4371373164f, 0.5188422971f), 260 | new Float3(0.9985120116f, 0.04659011161f, -0.02833944577f), new Float3(-0.3727687496f, -0.9082481361f, 0.1900757285f), new Float3(0.91737377f, -0.3483642108f, 0.1925298489f), new Float3(0.2714911074f, 0.4147529736f, -0.8684886582f), new Float3(0.5131763485f, -0.7116334161f, 0.4798207128f), new Float3(-0.8737353606f, 0.18886992f, -0.4482350644f), new Float3(0.8460043821f, -0.3725217914f, 0.3814499973f), new Float3(0.8978727456f, -0.1780209141f, -0.4026575304f), 261 | new Float3(0.2178065647f, -0.9698322841f, -0.1094789531f), new Float3(-0.1518031304f, -0.7788918132f, -0.6085091231f), new Float3(-0.2600384876f, -0.4755398075f, -0.8403819825f), new Float3(0.572313509f, -0.7474340931f, -0.3373418503f), new Float3(-0.7174141009f, 0.1699017182f, -0.6756111411f), new Float3(-0.684180784f, 0.02145707593f, -0.7289967412f), new Float3(-0.2007447902f, 0.06555605789f, -0.9774476623f), new Float3(-0.1148803697f, -0.8044887315f, 0.5827524187f), 262 | new Float3(-0.7870349638f, 0.03447489231f, 0.6159443543f), new Float3(-0.2015596421f, 0.6859872284f, 0.6991389226f), new Float3(-0.08581082512f, -0.10920836f, -0.9903080513f), new Float3(0.5532693395f, 0.7325250401f, -0.396610771f), new Float3(-0.1842489331f, -0.9777375055f, -0.1004076743f), new Float3(0.0775473789f, -0.9111505856f, 0.4047110257f), new Float3(0.1399838409f, 0.7601631212f, -0.6344734459f), new Float3(0.4484419361f, -0.845289248f, 0.2904925424f), 263 | }; 264 | 265 | [MethodImplAttribute(FN_INLINE)] 266 | private static int FastFloor(FN_DECIMAL f) { return (f >= 0 ? (int)f : (int)f - 1); } 267 | 268 | [MethodImplAttribute(FN_INLINE)] 269 | private static int FastRound(FN_DECIMAL f) { return (f >= 0) ? (int)(f + (FN_DECIMAL)0.5) : (int)(f - (FN_DECIMAL)0.5); } 270 | 271 | [MethodImplAttribute(FN_INLINE)] 272 | private static FN_DECIMAL Lerp(FN_DECIMAL a, FN_DECIMAL b, FN_DECIMAL t) { return a + t * (b - a); } 273 | 274 | [MethodImplAttribute(FN_INLINE)] 275 | private static FN_DECIMAL InterpHermiteFunc(FN_DECIMAL t) { return t * t * (3 - 2 * t); } 276 | 277 | [MethodImplAttribute(FN_INLINE)] 278 | private static FN_DECIMAL InterpQuinticFunc(FN_DECIMAL t) { return t * t * t * (t * (t * 6 - 15) + 10); } 279 | 280 | [MethodImplAttribute(FN_INLINE)] 281 | private static FN_DECIMAL CubicLerp(FN_DECIMAL a, FN_DECIMAL b, FN_DECIMAL c, FN_DECIMAL d, FN_DECIMAL t) 282 | { 283 | FN_DECIMAL p = (d - c) - (a - b); 284 | return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b; 285 | } 286 | 287 | private void CalculateFractalBounding() 288 | { 289 | FN_DECIMAL amp = m_gain; 290 | FN_DECIMAL ampFractal = 1; 291 | for (int i = 1; i < m_octaves; i++) 292 | { 293 | ampFractal += amp; 294 | amp *= m_gain; 295 | } 296 | m_fractalBounding = 1 / ampFractal; 297 | } 298 | 299 | // Hashing 300 | private const int X_PRIME = 1619; 301 | private const int Y_PRIME = 31337; 302 | private const int Z_PRIME = 6971; 303 | private const int W_PRIME = 1013; 304 | 305 | [MethodImplAttribute(FN_INLINE)] 306 | private static int Hash2D(int seed, int x, int y) 307 | { 308 | int hash = seed; 309 | hash ^= X_PRIME * x; 310 | hash ^= Y_PRIME * y; 311 | 312 | hash = hash * hash * hash * 60493; 313 | hash = (hash >> 13) ^ hash; 314 | 315 | return hash; 316 | } 317 | 318 | [MethodImplAttribute(FN_INLINE)] 319 | private static int Hash3D(int seed, int x, int y, int z) 320 | { 321 | int hash = seed; 322 | hash ^= X_PRIME * x; 323 | hash ^= Y_PRIME * y; 324 | hash ^= Z_PRIME * z; 325 | 326 | hash = hash * hash * hash * 60493; 327 | hash = (hash >> 13) ^ hash; 328 | 329 | return hash; 330 | } 331 | 332 | [MethodImplAttribute(FN_INLINE)] 333 | private static int Hash4D(int seed, int x, int y, int z, int w) 334 | { 335 | int hash = seed; 336 | hash ^= X_PRIME * x; 337 | hash ^= Y_PRIME * y; 338 | hash ^= Z_PRIME * z; 339 | hash ^= W_PRIME * w; 340 | 341 | hash = hash * hash * hash * 60493; 342 | hash = (hash >> 13) ^ hash; 343 | 344 | return hash; 345 | } 346 | 347 | [MethodImplAttribute(FN_INLINE)] 348 | private static FN_DECIMAL ValCoord2D(int seed, int x, int y) 349 | { 350 | int n = seed; 351 | n ^= X_PRIME * x; 352 | n ^= Y_PRIME * y; 353 | 354 | return (n * n * n * 60493) / (FN_DECIMAL)2147483648.0; 355 | } 356 | 357 | [MethodImplAttribute(FN_INLINE)] 358 | private static FN_DECIMAL ValCoord3D(int seed, int x, int y, int z) 359 | { 360 | int n = seed; 361 | n ^= X_PRIME * x; 362 | n ^= Y_PRIME * y; 363 | n ^= Z_PRIME * z; 364 | 365 | return (n * n * n * 60493) / (FN_DECIMAL)2147483648.0; 366 | } 367 | 368 | [MethodImplAttribute(FN_INLINE)] 369 | private static FN_DECIMAL ValCoord4D(int seed, int x, int y, int z, int w) 370 | { 371 | int n = seed; 372 | n ^= X_PRIME * x; 373 | n ^= Y_PRIME * y; 374 | n ^= Z_PRIME * z; 375 | n ^= W_PRIME * w; 376 | 377 | return (n * n * n * 60493) / (FN_DECIMAL)2147483648.0; 378 | } 379 | 380 | [MethodImplAttribute(FN_INLINE)] 381 | private static FN_DECIMAL GradCoord2D(int seed, int x, int y, FN_DECIMAL xd, FN_DECIMAL yd) 382 | { 383 | int hash = seed; 384 | hash ^= X_PRIME * x; 385 | hash ^= Y_PRIME * y; 386 | 387 | hash = hash * hash * hash * 60493; 388 | hash = (hash >> 13) ^ hash; 389 | 390 | Float2 g = GRAD_2D[hash & 7]; 391 | 392 | return xd * g.x + yd * g.y; 393 | } 394 | 395 | [MethodImplAttribute(FN_INLINE)] 396 | private static FN_DECIMAL GradCoord3D(int seed, int x, int y, int z, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd) 397 | { 398 | int hash = seed; 399 | hash ^= X_PRIME * x; 400 | hash ^= Y_PRIME * y; 401 | hash ^= Z_PRIME * z; 402 | 403 | hash = hash * hash * hash * 60493; 404 | hash = (hash >> 13) ^ hash; 405 | 406 | Float3 g = GRAD_3D[hash & 15]; 407 | 408 | return xd * g.x + yd * g.y + zd * g.z; 409 | } 410 | 411 | [MethodImplAttribute(FN_INLINE)] 412 | private static FN_DECIMAL GradCoord4D(int seed, int x, int y, int z, int w, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd, FN_DECIMAL wd) 413 | { 414 | int hash = seed; 415 | hash ^= X_PRIME * x; 416 | hash ^= Y_PRIME * y; 417 | hash ^= Z_PRIME * z; 418 | hash ^= W_PRIME * w; 419 | 420 | hash = hash * hash * hash * 60493; 421 | hash = (hash >> 13) ^ hash; 422 | 423 | hash &= 31; 424 | FN_DECIMAL a = yd, b = zd, c = wd; // X,Y,Z 425 | switch (hash >> 3) 426 | { // OR, DEPENDING ON HIGH ORDER 2 BITS: 427 | case 1: a = wd; b = xd; c = yd; break; // W,X,Y 428 | case 2: a = zd; b = wd; c = xd; break; // Z,W,X 429 | case 3: a = yd; b = zd; c = wd; break; // Y,Z,W 430 | } 431 | return ((hash & 4) == 0 ? -a : a) + ((hash & 2) == 0 ? -b : b) + ((hash & 1) == 0 ? -c : c); 432 | } 433 | 434 | public FN_DECIMAL GetNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 435 | { 436 | x *= m_frequency; 437 | y *= m_frequency; 438 | z *= m_frequency; 439 | 440 | switch (m_noiseType) 441 | { 442 | case NoiseType.Value: 443 | return SingleValue(m_seed, x, y, z); 444 | case NoiseType.ValueFractal: 445 | switch (m_fractalType) 446 | { 447 | case FractalType.FBM: 448 | return SingleValueFractalFBM(x, y, z); 449 | case FractalType.Billow: 450 | return SingleValueFractalBillow(x, y, z); 451 | case FractalType.RigidMulti: 452 | return SingleValueFractalRigidMulti(x, y, z); 453 | default: 454 | return 0; 455 | } 456 | case NoiseType.Perlin: 457 | return SinglePerlin(m_seed, x, y, z); 458 | case NoiseType.PerlinFractal: 459 | switch (m_fractalType) 460 | { 461 | case FractalType.FBM: 462 | return SinglePerlinFractalFBM(x, y, z); 463 | case FractalType.Billow: 464 | return SinglePerlinFractalBillow(x, y, z); 465 | case FractalType.RigidMulti: 466 | return SinglePerlinFractalRigidMulti(x, y, z); 467 | default: 468 | return 0; 469 | } 470 | case NoiseType.Simplex: 471 | return SingleSimplex(m_seed, x, y, z); 472 | case NoiseType.SimplexFractal: 473 | switch (m_fractalType) 474 | { 475 | case FractalType.FBM: 476 | return SingleSimplexFractalFBM(x, y, z); 477 | case FractalType.Billow: 478 | return SingleSimplexFractalBillow(x, y, z); 479 | case FractalType.RigidMulti: 480 | return SingleSimplexFractalRigidMulti(x, y, z); 481 | default: 482 | return 0; 483 | } 484 | case NoiseType.Cellular: 485 | switch (m_cellularReturnType) 486 | { 487 | case CellularReturnType.CellValue: 488 | case CellularReturnType.NoiseLookup: 489 | case CellularReturnType.Distance: 490 | return SingleCellular(x, y, z); 491 | default: 492 | return SingleCellular2Edge(x, y, z); 493 | } 494 | case NoiseType.WhiteNoise: 495 | return GetWhiteNoise(x, y, z); 496 | case NoiseType.Cubic: 497 | return SingleCubic(m_seed, x, y, z); 498 | case NoiseType.CubicFractal: 499 | switch (m_fractalType) 500 | { 501 | case FractalType.FBM: 502 | return SingleCubicFractalFBM(x, y, z); 503 | case FractalType.Billow: 504 | return SingleCubicFractalBillow(x, y, z); 505 | case FractalType.RigidMulti: 506 | return SingleCubicFractalRigidMulti(x, y, z); 507 | default: 508 | return 0; 509 | } 510 | default: 511 | return 0; 512 | } 513 | } 514 | 515 | public FN_DECIMAL GetNoise(FN_DECIMAL x, FN_DECIMAL y) 516 | { 517 | x *= m_frequency; 518 | y *= m_frequency; 519 | 520 | switch (m_noiseType) 521 | { 522 | case NoiseType.Value: 523 | return SingleValue(m_seed, x, y); 524 | case NoiseType.ValueFractal: 525 | switch (m_fractalType) 526 | { 527 | case FractalType.FBM: 528 | return SingleValueFractalFBM(x, y); 529 | case FractalType.Billow: 530 | return SingleValueFractalBillow(x, y); 531 | case FractalType.RigidMulti: 532 | return SingleValueFractalRigidMulti(x, y); 533 | default: 534 | return 0; 535 | } 536 | case NoiseType.Perlin: 537 | return SinglePerlin(m_seed, x, y); 538 | case NoiseType.PerlinFractal: 539 | switch (m_fractalType) 540 | { 541 | case FractalType.FBM: 542 | return SinglePerlinFractalFBM(x, y); 543 | case FractalType.Billow: 544 | return SinglePerlinFractalBillow(x, y); 545 | case FractalType.RigidMulti: 546 | return SinglePerlinFractalRigidMulti(x, y); 547 | default: 548 | return 0; 549 | } 550 | case NoiseType.Simplex: 551 | return SingleSimplex(m_seed, x, y); 552 | case NoiseType.SimplexFractal: 553 | switch (m_fractalType) 554 | { 555 | case FractalType.FBM: 556 | return SingleSimplexFractalFBM(x, y); 557 | case FractalType.Billow: 558 | return SingleSimplexFractalBillow(x, y); 559 | case FractalType.RigidMulti: 560 | return SingleSimplexFractalRigidMulti(x, y); 561 | default: 562 | return 0; 563 | } 564 | case NoiseType.Cellular: 565 | switch (m_cellularReturnType) 566 | { 567 | case CellularReturnType.CellValue: 568 | case CellularReturnType.NoiseLookup: 569 | case CellularReturnType.Distance: 570 | return SingleCellular(x, y); 571 | default: 572 | return SingleCellular2Edge(x, y); 573 | } 574 | case NoiseType.WhiteNoise: 575 | return GetWhiteNoise(x, y); 576 | case NoiseType.Cubic: 577 | return SingleCubic(m_seed, x, y); 578 | case NoiseType.CubicFractal: 579 | switch (m_fractalType) 580 | { 581 | case FractalType.FBM: 582 | return SingleCubicFractalFBM(x, y); 583 | case FractalType.Billow: 584 | return SingleCubicFractalBillow(x, y); 585 | case FractalType.RigidMulti: 586 | return SingleCubicFractalRigidMulti(x, y); 587 | default: 588 | return 0; 589 | } 590 | default: 591 | return 0; 592 | } 593 | } 594 | 595 | // White Noise 596 | [MethodImplAttribute(FN_INLINE)] 597 | private int FloatCast2Int(FN_DECIMAL f) 598 | { 599 | var i = BitConverter.DoubleToInt64Bits(f); 600 | 601 | return (int)(i ^ (i >> 32)); 602 | } 603 | 604 | public FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) 605 | { 606 | int xi = FloatCast2Int(x); 607 | int yi = FloatCast2Int(y); 608 | int zi = FloatCast2Int(z); 609 | int wi = FloatCast2Int(w); 610 | 611 | return ValCoord4D(m_seed, xi, yi, zi, wi); 612 | } 613 | 614 | public FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 615 | { 616 | int xi = FloatCast2Int(x); 617 | int yi = FloatCast2Int(y); 618 | int zi = FloatCast2Int(z); 619 | 620 | return ValCoord3D(m_seed, xi, yi, zi); 621 | } 622 | 623 | public FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y) 624 | { 625 | int xi = FloatCast2Int(x); 626 | int yi = FloatCast2Int(y); 627 | 628 | return ValCoord2D(m_seed, xi, yi); 629 | } 630 | 631 | public FN_DECIMAL GetWhiteNoiseInt(int x, int y, int z, int w) 632 | { 633 | return ValCoord4D(m_seed, x, y, z, w); 634 | } 635 | 636 | public FN_DECIMAL GetWhiteNoiseInt(int x, int y, int z) 637 | { 638 | return ValCoord3D(m_seed, x, y, z); 639 | } 640 | 641 | public FN_DECIMAL GetWhiteNoiseInt(int x, int y) 642 | { 643 | return ValCoord2D(m_seed, x, y); 644 | } 645 | 646 | // Value Noise 647 | public FN_DECIMAL GetValueFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 648 | { 649 | x *= m_frequency; 650 | y *= m_frequency; 651 | z *= m_frequency; 652 | 653 | switch (m_fractalType) 654 | { 655 | case FractalType.FBM: 656 | return SingleValueFractalFBM(x, y, z); 657 | case FractalType.Billow: 658 | return SingleValueFractalBillow(x, y, z); 659 | case FractalType.RigidMulti: 660 | return SingleValueFractalRigidMulti(x, y, z); 661 | default: 662 | return 0; 663 | } 664 | } 665 | 666 | private FN_DECIMAL SingleValueFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 667 | { 668 | int seed = m_seed; 669 | FN_DECIMAL sum = SingleValue(seed, x, y, z); 670 | FN_DECIMAL amp = 1; 671 | 672 | for (int i = 1; i < m_octaves; i++) 673 | { 674 | x *= m_lacunarity; 675 | y *= m_lacunarity; 676 | z *= m_lacunarity; 677 | 678 | amp *= m_gain; 679 | sum += SingleValue(++seed, x, y, z) * amp; 680 | } 681 | 682 | return sum * m_fractalBounding; 683 | } 684 | 685 | private FN_DECIMAL SingleValueFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 686 | { 687 | int seed = m_seed; 688 | FN_DECIMAL sum = Math.Abs(SingleValue(seed, x, y, z)) * 2 - 1; 689 | FN_DECIMAL amp = 1; 690 | 691 | for (int i = 1; i < m_octaves; i++) 692 | { 693 | x *= m_lacunarity; 694 | y *= m_lacunarity; 695 | z *= m_lacunarity; 696 | 697 | amp *= m_gain; 698 | sum += (Math.Abs(SingleValue(++seed, x, y, z)) * 2 - 1) * amp; 699 | } 700 | 701 | return sum * m_fractalBounding; 702 | } 703 | 704 | private FN_DECIMAL SingleValueFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 705 | { 706 | int seed = m_seed; 707 | FN_DECIMAL sum = 1 - Math.Abs(SingleValue(seed, x, y, z)); 708 | FN_DECIMAL amp = 1; 709 | 710 | for (int i = 1; i < m_octaves; i++) 711 | { 712 | x *= m_lacunarity; 713 | y *= m_lacunarity; 714 | z *= m_lacunarity; 715 | 716 | amp *= m_gain; 717 | sum -= (1 - Math.Abs(SingleValue(++seed, x, y, z))) * amp; 718 | } 719 | 720 | return sum; 721 | } 722 | 723 | public FN_DECIMAL GetValue(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 724 | { 725 | return SingleValue(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); 726 | } 727 | 728 | private FN_DECIMAL SingleValue(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 729 | { 730 | int x0 = FastFloor(x); 731 | int y0 = FastFloor(y); 732 | int z0 = FastFloor(z); 733 | int x1 = x0 + 1; 734 | int y1 = y0 + 1; 735 | int z1 = z0 + 1; 736 | 737 | FN_DECIMAL xs, ys, zs; 738 | switch (m_interp) 739 | { 740 | default: 741 | case Interp.Linear: 742 | xs = x - x0; 743 | ys = y - y0; 744 | zs = z - z0; 745 | break; 746 | case Interp.Hermite: 747 | xs = InterpHermiteFunc(x - x0); 748 | ys = InterpHermiteFunc(y - y0); 749 | zs = InterpHermiteFunc(z - z0); 750 | break; 751 | case Interp.Quintic: 752 | xs = InterpQuinticFunc(x - x0); 753 | ys = InterpQuinticFunc(y - y0); 754 | zs = InterpQuinticFunc(z - z0); 755 | break; 756 | } 757 | 758 | FN_DECIMAL xf00 = Lerp(ValCoord3D(seed, x0, y0, z0), ValCoord3D(seed, x1, y0, z0), xs); 759 | FN_DECIMAL xf10 = Lerp(ValCoord3D(seed, x0, y1, z0), ValCoord3D(seed, x1, y1, z0), xs); 760 | FN_DECIMAL xf01 = Lerp(ValCoord3D(seed, x0, y0, z1), ValCoord3D(seed, x1, y0, z1), xs); 761 | FN_DECIMAL xf11 = Lerp(ValCoord3D(seed, x0, y1, z1), ValCoord3D(seed, x1, y1, z1), xs); 762 | 763 | FN_DECIMAL yf0 = Lerp(xf00, xf10, ys); 764 | FN_DECIMAL yf1 = Lerp(xf01, xf11, ys); 765 | 766 | return Lerp(yf0, yf1, zs); 767 | } 768 | 769 | public FN_DECIMAL GetValueFractal(FN_DECIMAL x, FN_DECIMAL y) 770 | { 771 | x *= m_frequency; 772 | y *= m_frequency; 773 | 774 | switch (m_fractalType) 775 | { 776 | case FractalType.FBM: 777 | return SingleValueFractalFBM(x, y); 778 | case FractalType.Billow: 779 | return SingleValueFractalBillow(x, y); 780 | case FractalType.RigidMulti: 781 | return SingleValueFractalRigidMulti(x, y); 782 | default: 783 | return 0; 784 | } 785 | } 786 | 787 | private FN_DECIMAL SingleValueFractalFBM(FN_DECIMAL x, FN_DECIMAL y) 788 | { 789 | int seed = m_seed; 790 | FN_DECIMAL sum = SingleValue(seed, x, y); 791 | FN_DECIMAL amp = 1; 792 | 793 | for (int i = 1; i < m_octaves; i++) 794 | { 795 | x *= m_lacunarity; 796 | y *= m_lacunarity; 797 | 798 | amp *= m_gain; 799 | sum += SingleValue(++seed, x, y) * amp; 800 | } 801 | 802 | return sum * m_fractalBounding; 803 | } 804 | 805 | private FN_DECIMAL SingleValueFractalBillow(FN_DECIMAL x, FN_DECIMAL y) 806 | { 807 | int seed = m_seed; 808 | FN_DECIMAL sum = Math.Abs(SingleValue(seed, x, y)) * 2 - 1; 809 | FN_DECIMAL amp = 1; 810 | 811 | for (int i = 1; i < m_octaves; i++) 812 | { 813 | x *= m_lacunarity; 814 | y *= m_lacunarity; 815 | amp *= m_gain; 816 | sum += (Math.Abs(SingleValue(++seed, x, y)) * 2 - 1) * amp; 817 | } 818 | 819 | return sum * m_fractalBounding; 820 | } 821 | 822 | private FN_DECIMAL SingleValueFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) 823 | { 824 | int seed = m_seed; 825 | FN_DECIMAL sum = 1 - Math.Abs(SingleValue(seed, x, y)); 826 | FN_DECIMAL amp = 1; 827 | 828 | for (int i = 1; i < m_octaves; i++) 829 | { 830 | x *= m_lacunarity; 831 | y *= m_lacunarity; 832 | 833 | amp *= m_gain; 834 | sum -= (1 - Math.Abs(SingleValue(++seed, x, y))) * amp; 835 | } 836 | 837 | return sum; 838 | } 839 | 840 | public FN_DECIMAL GetValue(FN_DECIMAL x, FN_DECIMAL y) 841 | { 842 | return SingleValue(m_seed, x * m_frequency, y * m_frequency); 843 | } 844 | 845 | private FN_DECIMAL SingleValue(int seed, FN_DECIMAL x, FN_DECIMAL y) 846 | { 847 | int x0 = FastFloor(x); 848 | int y0 = FastFloor(y); 849 | int x1 = x0 + 1; 850 | int y1 = y0 + 1; 851 | 852 | FN_DECIMAL xs, ys; 853 | switch (m_interp) 854 | { 855 | default: 856 | case Interp.Linear: 857 | xs = x - x0; 858 | ys = y - y0; 859 | break; 860 | case Interp.Hermite: 861 | xs = InterpHermiteFunc(x - x0); 862 | ys = InterpHermiteFunc(y - y0); 863 | break; 864 | case Interp.Quintic: 865 | xs = InterpQuinticFunc(x - x0); 866 | ys = InterpQuinticFunc(y - y0); 867 | break; 868 | } 869 | 870 | FN_DECIMAL xf0 = Lerp(ValCoord2D(seed, x0, y0), ValCoord2D(seed, x1, y0), xs); 871 | FN_DECIMAL xf1 = Lerp(ValCoord2D(seed, x0, y1), ValCoord2D(seed, x1, y1), xs); 872 | 873 | return Lerp(xf0, xf1, ys); 874 | } 875 | 876 | // Gradient Noise 877 | public FN_DECIMAL GetPerlinFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 878 | { 879 | x *= m_frequency; 880 | y *= m_frequency; 881 | z *= m_frequency; 882 | 883 | switch (m_fractalType) 884 | { 885 | case FractalType.FBM: 886 | return SinglePerlinFractalFBM(x, y, z); 887 | case FractalType.Billow: 888 | return SinglePerlinFractalBillow(x, y, z); 889 | case FractalType.RigidMulti: 890 | return SinglePerlinFractalRigidMulti(x, y, z); 891 | default: 892 | return 0; 893 | } 894 | } 895 | 896 | private FN_DECIMAL SinglePerlinFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 897 | { 898 | int seed = m_seed; 899 | FN_DECIMAL sum = SinglePerlin(seed, x, y, z); 900 | FN_DECIMAL amp = 1; 901 | 902 | for (int i = 1; i < m_octaves; i++) 903 | { 904 | x *= m_lacunarity; 905 | y *= m_lacunarity; 906 | z *= m_lacunarity; 907 | 908 | amp *= m_gain; 909 | sum += SinglePerlin(++seed, x, y, z) * amp; 910 | } 911 | 912 | return sum * m_fractalBounding; 913 | } 914 | 915 | private FN_DECIMAL SinglePerlinFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 916 | { 917 | int seed = m_seed; 918 | FN_DECIMAL sum = Math.Abs(SinglePerlin(seed, x, y, z)) * 2 - 1; 919 | FN_DECIMAL amp = 1; 920 | 921 | for (int i = 1; i < m_octaves; i++) 922 | { 923 | x *= m_lacunarity; 924 | y *= m_lacunarity; 925 | z *= m_lacunarity; 926 | 927 | amp *= m_gain; 928 | sum += (Math.Abs(SinglePerlin(++seed, x, y, z)) * 2 - 1) * amp; 929 | } 930 | 931 | return sum * m_fractalBounding; 932 | } 933 | 934 | private FN_DECIMAL SinglePerlinFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 935 | { 936 | int seed = m_seed; 937 | FN_DECIMAL sum = 1 - Math.Abs(SinglePerlin(seed, x, y, z)); 938 | FN_DECIMAL amp = 1; 939 | 940 | for (int i = 1; i < m_octaves; i++) 941 | { 942 | x *= m_lacunarity; 943 | y *= m_lacunarity; 944 | z *= m_lacunarity; 945 | 946 | amp *= m_gain; 947 | sum -= (1 - Math.Abs(SinglePerlin(++seed, x, y, z))) * amp; 948 | } 949 | 950 | return sum; 951 | } 952 | 953 | public FN_DECIMAL GetPerlin(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 954 | { 955 | return SinglePerlin(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); 956 | } 957 | 958 | private FN_DECIMAL SinglePerlin(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 959 | { 960 | int x0 = FastFloor(x); 961 | int y0 = FastFloor(y); 962 | int z0 = FastFloor(z); 963 | int x1 = x0 + 1; 964 | int y1 = y0 + 1; 965 | int z1 = z0 + 1; 966 | 967 | FN_DECIMAL xs, ys, zs; 968 | switch (m_interp) 969 | { 970 | default: 971 | case Interp.Linear: 972 | xs = x - x0; 973 | ys = y - y0; 974 | zs = z - z0; 975 | break; 976 | case Interp.Hermite: 977 | xs = InterpHermiteFunc(x - x0); 978 | ys = InterpHermiteFunc(y - y0); 979 | zs = InterpHermiteFunc(z - z0); 980 | break; 981 | case Interp.Quintic: 982 | xs = InterpQuinticFunc(x - x0); 983 | ys = InterpQuinticFunc(y - y0); 984 | zs = InterpQuinticFunc(z - z0); 985 | break; 986 | } 987 | 988 | FN_DECIMAL xd0 = x - x0; 989 | FN_DECIMAL yd0 = y - y0; 990 | FN_DECIMAL zd0 = z - z0; 991 | FN_DECIMAL xd1 = xd0 - 1; 992 | FN_DECIMAL yd1 = yd0 - 1; 993 | FN_DECIMAL zd1 = zd0 - 1; 994 | 995 | FN_DECIMAL xf00 = Lerp(GradCoord3D(seed, x0, y0, z0, xd0, yd0, zd0), GradCoord3D(seed, x1, y0, z0, xd1, yd0, zd0), xs); 996 | FN_DECIMAL xf10 = Lerp(GradCoord3D(seed, x0, y1, z0, xd0, yd1, zd0), GradCoord3D(seed, x1, y1, z0, xd1, yd1, zd0), xs); 997 | FN_DECIMAL xf01 = Lerp(GradCoord3D(seed, x0, y0, z1, xd0, yd0, zd1), GradCoord3D(seed, x1, y0, z1, xd1, yd0, zd1), xs); 998 | FN_DECIMAL xf11 = Lerp(GradCoord3D(seed, x0, y1, z1, xd0, yd1, zd1), GradCoord3D(seed, x1, y1, z1, xd1, yd1, zd1), xs); 999 | 1000 | FN_DECIMAL yf0 = Lerp(xf00, xf10, ys); 1001 | FN_DECIMAL yf1 = Lerp(xf01, xf11, ys); 1002 | 1003 | return Lerp(yf0, yf1, zs); 1004 | } 1005 | 1006 | public FN_DECIMAL GetPerlinFractal(FN_DECIMAL x, FN_DECIMAL y) 1007 | { 1008 | x *= m_frequency; 1009 | y *= m_frequency; 1010 | 1011 | switch (m_fractalType) 1012 | { 1013 | case FractalType.FBM: 1014 | return SinglePerlinFractalFBM(x, y); 1015 | case FractalType.Billow: 1016 | return SinglePerlinFractalBillow(x, y); 1017 | case FractalType.RigidMulti: 1018 | return SinglePerlinFractalRigidMulti(x, y); 1019 | default: 1020 | return 0; 1021 | } 1022 | } 1023 | 1024 | private FN_DECIMAL SinglePerlinFractalFBM(FN_DECIMAL x, FN_DECIMAL y) 1025 | { 1026 | int seed = m_seed; 1027 | FN_DECIMAL sum = SinglePerlin(seed, x, y); 1028 | FN_DECIMAL amp = 1; 1029 | 1030 | for (int i = 1; i < m_octaves; i++) 1031 | { 1032 | x *= m_lacunarity; 1033 | y *= m_lacunarity; 1034 | 1035 | amp *= m_gain; 1036 | sum += SinglePerlin(++seed, x, y) * amp; 1037 | } 1038 | 1039 | return sum * m_fractalBounding; 1040 | } 1041 | 1042 | private FN_DECIMAL SinglePerlinFractalBillow(FN_DECIMAL x, FN_DECIMAL y) 1043 | { 1044 | int seed = m_seed; 1045 | FN_DECIMAL sum = Math.Abs(SinglePerlin(seed, x, y)) * 2 - 1; 1046 | FN_DECIMAL amp = 1; 1047 | 1048 | for (int i = 1; i < m_octaves; i++) 1049 | { 1050 | x *= m_lacunarity; 1051 | y *= m_lacunarity; 1052 | 1053 | amp *= m_gain; 1054 | sum += (Math.Abs(SinglePerlin(++seed, x, y)) * 2 - 1) * amp; 1055 | } 1056 | 1057 | return sum * m_fractalBounding; 1058 | } 1059 | 1060 | private FN_DECIMAL SinglePerlinFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) 1061 | { 1062 | int seed = m_seed; 1063 | FN_DECIMAL sum = 1 - Math.Abs(SinglePerlin(seed, x, y)); 1064 | FN_DECIMAL amp = 1; 1065 | 1066 | for (int i = 1; i < m_octaves; i++) 1067 | { 1068 | x *= m_lacunarity; 1069 | y *= m_lacunarity; 1070 | 1071 | amp *= m_gain; 1072 | sum -= (1 - Math.Abs(SinglePerlin(++seed, x, y))) * amp; 1073 | } 1074 | 1075 | return sum; 1076 | } 1077 | 1078 | public FN_DECIMAL GetPerlin(FN_DECIMAL x, FN_DECIMAL y) 1079 | { 1080 | return SinglePerlin(m_seed, x * m_frequency, y * m_frequency); 1081 | } 1082 | 1083 | private FN_DECIMAL SinglePerlin(int seed, FN_DECIMAL x, FN_DECIMAL y) 1084 | { 1085 | int x0 = FastFloor(x); 1086 | int y0 = FastFloor(y); 1087 | int x1 = x0 + 1; 1088 | int y1 = y0 + 1; 1089 | 1090 | FN_DECIMAL xs, ys; 1091 | switch (m_interp) 1092 | { 1093 | default: 1094 | case Interp.Linear: 1095 | xs = x - x0; 1096 | ys = y - y0; 1097 | break; 1098 | case Interp.Hermite: 1099 | xs = InterpHermiteFunc(x - x0); 1100 | ys = InterpHermiteFunc(y - y0); 1101 | break; 1102 | case Interp.Quintic: 1103 | xs = InterpQuinticFunc(x - x0); 1104 | ys = InterpQuinticFunc(y - y0); 1105 | break; 1106 | } 1107 | 1108 | FN_DECIMAL xd0 = x - x0; 1109 | FN_DECIMAL yd0 = y - y0; 1110 | FN_DECIMAL xd1 = xd0 - 1; 1111 | FN_DECIMAL yd1 = yd0 - 1; 1112 | 1113 | FN_DECIMAL xf0 = Lerp(GradCoord2D(seed, x0, y0, xd0, yd0), GradCoord2D(seed, x1, y0, xd1, yd0), xs); 1114 | FN_DECIMAL xf1 = Lerp(GradCoord2D(seed, x0, y1, xd0, yd1), GradCoord2D(seed, x1, y1, xd1, yd1), xs); 1115 | 1116 | return Lerp(xf0, xf1, ys); 1117 | } 1118 | 1119 | // Simplex Noise 1120 | public FN_DECIMAL GetSimplexFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1121 | { 1122 | x *= m_frequency; 1123 | y *= m_frequency; 1124 | z *= m_frequency; 1125 | 1126 | switch (m_fractalType) 1127 | { 1128 | case FractalType.FBM: 1129 | return SingleSimplexFractalFBM(x, y, z); 1130 | case FractalType.Billow: 1131 | return SingleSimplexFractalBillow(x, y, z); 1132 | case FractalType.RigidMulti: 1133 | return SingleSimplexFractalRigidMulti(x, y, z); 1134 | default: 1135 | return 0; 1136 | } 1137 | } 1138 | 1139 | private FN_DECIMAL SingleSimplexFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1140 | { 1141 | int seed = m_seed; 1142 | FN_DECIMAL sum = SingleSimplex(seed, x, y, z); 1143 | FN_DECIMAL amp = 1; 1144 | 1145 | for (int i = 1; i < m_octaves; i++) 1146 | { 1147 | x *= m_lacunarity; 1148 | y *= m_lacunarity; 1149 | z *= m_lacunarity; 1150 | 1151 | amp *= m_gain; 1152 | sum += SingleSimplex(++seed, x, y, z) * amp; 1153 | } 1154 | 1155 | return sum * m_fractalBounding; 1156 | } 1157 | 1158 | private FN_DECIMAL SingleSimplexFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1159 | { 1160 | int seed = m_seed; 1161 | FN_DECIMAL sum = Math.Abs(SingleSimplex(seed, x, y, z)) * 2 - 1; 1162 | FN_DECIMAL amp = 1; 1163 | 1164 | for (int i = 1; i < m_octaves; i++) 1165 | { 1166 | x *= m_lacunarity; 1167 | y *= m_lacunarity; 1168 | z *= m_lacunarity; 1169 | 1170 | amp *= m_gain; 1171 | sum += (Math.Abs(SingleSimplex(++seed, x, y, z)) * 2 - 1) * amp; 1172 | } 1173 | 1174 | return sum * m_fractalBounding; 1175 | } 1176 | 1177 | private FN_DECIMAL SingleSimplexFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1178 | { 1179 | int seed = m_seed; 1180 | FN_DECIMAL sum = 1 - Math.Abs(SingleSimplex(seed, x, y, z)); 1181 | FN_DECIMAL amp = 1; 1182 | 1183 | for (int i = 1; i < m_octaves; i++) 1184 | { 1185 | x *= m_lacunarity; 1186 | y *= m_lacunarity; 1187 | z *= m_lacunarity; 1188 | 1189 | amp *= m_gain; 1190 | sum -= (1 - Math.Abs(SingleSimplex(++seed, x, y, z))) * amp; 1191 | } 1192 | 1193 | return sum; 1194 | } 1195 | 1196 | public FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1197 | { 1198 | return SingleSimplex(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); 1199 | } 1200 | 1201 | private const FN_DECIMAL F3 = (FN_DECIMAL)(1.0 / 3.0); 1202 | private const FN_DECIMAL G3 = (FN_DECIMAL)(1.0 / 6.0); 1203 | private const FN_DECIMAL G33 = G3 * 3 - 1; 1204 | 1205 | private FN_DECIMAL SingleSimplex(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1206 | { 1207 | FN_DECIMAL t = (x + y + z) * F3; 1208 | int i = FastFloor(x + t); 1209 | int j = FastFloor(y + t); 1210 | int k = FastFloor(z + t); 1211 | 1212 | t = (i + j + k) * G3; 1213 | FN_DECIMAL x0 = x - (i - t); 1214 | FN_DECIMAL y0 = y - (j - t); 1215 | FN_DECIMAL z0 = z - (k - t); 1216 | 1217 | int i1, j1, k1; 1218 | int i2, j2, k2; 1219 | 1220 | if (x0 >= y0) 1221 | { 1222 | if (y0 >= z0) 1223 | { 1224 | i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; 1225 | } 1226 | else if (x0 >= z0) 1227 | { 1228 | i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; 1229 | } 1230 | else // x0 < z0 1231 | { 1232 | i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; 1233 | } 1234 | } 1235 | else // x0 < y0 1236 | { 1237 | if (y0 < z0) 1238 | { 1239 | i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; 1240 | } 1241 | else if (x0 < z0) 1242 | { 1243 | i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; 1244 | } 1245 | else // x0 >= z0 1246 | { 1247 | i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; 1248 | } 1249 | } 1250 | 1251 | FN_DECIMAL x1 = x0 - i1 + G3; 1252 | FN_DECIMAL y1 = y0 - j1 + G3; 1253 | FN_DECIMAL z1 = z0 - k1 + G3; 1254 | FN_DECIMAL x2 = x0 - i2 + F3; 1255 | FN_DECIMAL y2 = y0 - j2 + F3; 1256 | FN_DECIMAL z2 = z0 - k2 + F3; 1257 | FN_DECIMAL x3 = x0 + G33; 1258 | FN_DECIMAL y3 = y0 + G33; 1259 | FN_DECIMAL z3 = z0 + G33; 1260 | 1261 | FN_DECIMAL n0, n1, n2, n3; 1262 | 1263 | t = (FN_DECIMAL)0.6 - x0 * x0 - y0 * y0 - z0 * z0; 1264 | if (t < 0) n0 = 0; 1265 | else 1266 | { 1267 | t *= t; 1268 | n0 = t * t * GradCoord3D(seed, i, j, k, x0, y0, z0); 1269 | } 1270 | 1271 | t = (FN_DECIMAL)0.6 - x1 * x1 - y1 * y1 - z1 * z1; 1272 | if (t < 0) n1 = 0; 1273 | else 1274 | { 1275 | t *= t; 1276 | n1 = t * t * GradCoord3D(seed, i + i1, j + j1, k + k1, x1, y1, z1); 1277 | } 1278 | 1279 | t = (FN_DECIMAL)0.6 - x2 * x2 - y2 * y2 - z2 * z2; 1280 | if (t < 0) n2 = 0; 1281 | else 1282 | { 1283 | t *= t; 1284 | n2 = t * t * GradCoord3D(seed, i + i2, j + j2, k + k2, x2, y2, z2); 1285 | } 1286 | 1287 | t = (FN_DECIMAL)0.6 - x3 * x3 - y3 * y3 - z3 * z3; 1288 | if (t < 0) n3 = 0; 1289 | else 1290 | { 1291 | t *= t; 1292 | n3 = t * t * GradCoord3D(seed, i + 1, j + 1, k + 1, x3, y3, z3); 1293 | } 1294 | 1295 | return 32 * (n0 + n1 + n2 + n3); 1296 | } 1297 | 1298 | public FN_DECIMAL GetSimplexFractal(FN_DECIMAL x, FN_DECIMAL y) 1299 | { 1300 | x *= m_frequency; 1301 | y *= m_frequency; 1302 | 1303 | switch (m_fractalType) 1304 | { 1305 | case FractalType.FBM: 1306 | return SingleSimplexFractalFBM(x, y); 1307 | case FractalType.Billow: 1308 | return SingleSimplexFractalBillow(x, y); 1309 | case FractalType.RigidMulti: 1310 | return SingleSimplexFractalRigidMulti(x, y); 1311 | default: 1312 | return 0; 1313 | } 1314 | } 1315 | 1316 | private FN_DECIMAL SingleSimplexFractalFBM(FN_DECIMAL x, FN_DECIMAL y) 1317 | { 1318 | int seed = m_seed; 1319 | FN_DECIMAL sum = SingleSimplex(seed, x, y); 1320 | FN_DECIMAL amp = 1; 1321 | 1322 | for (int i = 1; i < m_octaves; i++) 1323 | { 1324 | x *= m_lacunarity; 1325 | y *= m_lacunarity; 1326 | 1327 | amp *= m_gain; 1328 | sum += SingleSimplex(++seed, x, y) * amp; 1329 | } 1330 | 1331 | return sum * m_fractalBounding; 1332 | } 1333 | 1334 | private FN_DECIMAL SingleSimplexFractalBillow(FN_DECIMAL x, FN_DECIMAL y) 1335 | { 1336 | int seed = m_seed; 1337 | FN_DECIMAL sum = Math.Abs(SingleSimplex(seed, x, y)) * 2 - 1; 1338 | FN_DECIMAL amp = 1; 1339 | 1340 | for (int i = 1; i < m_octaves; i++) 1341 | { 1342 | x *= m_lacunarity; 1343 | y *= m_lacunarity; 1344 | 1345 | amp *= m_gain; 1346 | sum += (Math.Abs(SingleSimplex(++seed, x, y)) * 2 - 1) * amp; 1347 | } 1348 | 1349 | return sum * m_fractalBounding; 1350 | } 1351 | 1352 | private FN_DECIMAL SingleSimplexFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) 1353 | { 1354 | int seed = m_seed; 1355 | FN_DECIMAL sum = 1 - Math.Abs(SingleSimplex(seed, x, y)); 1356 | FN_DECIMAL amp = 1; 1357 | 1358 | for (int i = 1; i < m_octaves; i++) 1359 | { 1360 | x *= m_lacunarity; 1361 | y *= m_lacunarity; 1362 | 1363 | amp *= m_gain; 1364 | sum -= (1 - Math.Abs(SingleSimplex(++seed, x, y))) * amp; 1365 | } 1366 | 1367 | return sum; 1368 | } 1369 | 1370 | public FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y) 1371 | { 1372 | return SingleSimplex(m_seed, x * m_frequency, y * m_frequency); 1373 | } 1374 | 1375 | //private const FN_DECIMAL F2 = (FN_DECIMAL)(1.0 / 2.0); 1376 | //private const FN_DECIMAL G2 = (FN_DECIMAL)(1.0 / 4.0); 1377 | 1378 | private const FN_DECIMAL SQRT3 = (FN_DECIMAL)1.7320508075688772935274463415059; 1379 | private const FN_DECIMAL F2 = (FN_DECIMAL)0.5 * (SQRT3 - (FN_DECIMAL)1.0); 1380 | private const FN_DECIMAL G2 = ((FN_DECIMAL)3.0 - SQRT3) / (FN_DECIMAL)6.0; 1381 | 1382 | private FN_DECIMAL SingleSimplex(int seed, FN_DECIMAL x, FN_DECIMAL y) 1383 | { 1384 | FN_DECIMAL t = (x + y) * F2; 1385 | int i = FastFloor(x + t); 1386 | int j = FastFloor(y + t); 1387 | 1388 | t = (i + j) * G2; 1389 | FN_DECIMAL X0 = i - t; 1390 | FN_DECIMAL Y0 = j - t; 1391 | 1392 | FN_DECIMAL x0 = x - X0; 1393 | FN_DECIMAL y0 = y - Y0; 1394 | 1395 | int i1, j1; 1396 | if (x0 > y0) 1397 | { 1398 | i1 = 1; j1 = 0; 1399 | } 1400 | else 1401 | { 1402 | i1 = 0; j1 = 1; 1403 | } 1404 | 1405 | FN_DECIMAL x1 = x0 - i1 + G2; 1406 | FN_DECIMAL y1 = y0 - j1 + G2; 1407 | FN_DECIMAL x2 = x0 - 1 + 2*G2; 1408 | FN_DECIMAL y2 = y0 - 1 + 2*G2; 1409 | 1410 | FN_DECIMAL n0, n1, n2; 1411 | 1412 | t = (FN_DECIMAL)0.5 - x0 * x0 - y0 * y0; 1413 | if (t < 0) n0 = 0; 1414 | else 1415 | { 1416 | t *= t; 1417 | n0 = t * t * GradCoord2D(seed, i, j, x0, y0); 1418 | } 1419 | 1420 | t = (FN_DECIMAL)0.5 - x1 * x1 - y1 * y1; 1421 | if (t < 0) n1 = 0; 1422 | else 1423 | { 1424 | t *= t; 1425 | n1 = t * t * GradCoord2D(seed, i + i1, j + j1, x1, y1); 1426 | } 1427 | 1428 | t = (FN_DECIMAL)0.5 - x2 * x2 - y2 * y2; 1429 | if (t < 0) n2 = 0; 1430 | else 1431 | { 1432 | t *= t; 1433 | n2 = t * t * GradCoord2D(seed, i + 1, j + 1, x2, y2); 1434 | } 1435 | 1436 | return 50 * (n0 + n1 + n2); 1437 | } 1438 | 1439 | public FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) 1440 | { 1441 | return SingleSimplex(m_seed, x * m_frequency, y * m_frequency, z * m_frequency, w * m_frequency); 1442 | } 1443 | 1444 | private static readonly byte[] SIMPLEX_4D = 1445 | { 1446 | 0,1,2,3,0,1,3,2,0,0,0,0,0,2,3,1,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,0, 1447 | 0,2,1,3,0,0,0,0,0,3,1,2,0,3,2,1,0,0,0,0,0,0,0,0,0,0,0,0,1,3,2,0, 1448 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1449 | 1,2,0,3,0,0,0,0,1,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,2,3,0,1,2,3,1,0, 1450 | 1,0,2,3,1,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,2,0,3,1,0,0,0,0,2,1,3,0, 1451 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1452 | 2,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,2,3,0,2,1,0,0,0,0,3,1,2,0, 1453 | 2,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,3,1,0,2,0,0,0,0,3,2,0,1,3,2,1,0 1454 | }; 1455 | 1456 | private const FN_DECIMAL F4 = (FN_DECIMAL)((2.23606797 - 1.0) / 4.0); 1457 | private const FN_DECIMAL G4 = (FN_DECIMAL)((5.0 - 2.23606797) / 20.0); 1458 | 1459 | private FN_DECIMAL SingleSimplex(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) 1460 | { 1461 | FN_DECIMAL n0, n1, n2, n3, n4; 1462 | FN_DECIMAL t = (x + y + z + w) * F4; 1463 | int i = FastFloor(x + t); 1464 | int j = FastFloor(y + t); 1465 | int k = FastFloor(z + t); 1466 | int l = FastFloor(w + t); 1467 | t = (i + j + k + l) * G4; 1468 | FN_DECIMAL X0 = i - t; 1469 | FN_DECIMAL Y0 = j - t; 1470 | FN_DECIMAL Z0 = k - t; 1471 | FN_DECIMAL W0 = l - t; 1472 | FN_DECIMAL x0 = x - X0; 1473 | FN_DECIMAL y0 = y - Y0; 1474 | FN_DECIMAL z0 = z - Z0; 1475 | FN_DECIMAL w0 = w - W0; 1476 | 1477 | int c = (x0 > y0) ? 32 : 0; 1478 | c += (x0 > z0) ? 16 : 0; 1479 | c += (y0 > z0) ? 8 : 0; 1480 | c += (x0 > w0) ? 4 : 0; 1481 | c += (y0 > w0) ? 2 : 0; 1482 | c += (z0 > w0) ? 1 : 0; 1483 | c <<= 2; 1484 | 1485 | int i1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; 1486 | int i2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; 1487 | int i3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; 1488 | int j1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; 1489 | int j2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; 1490 | int j3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; 1491 | int k1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; 1492 | int k2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; 1493 | int k3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; 1494 | int l1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; 1495 | int l2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; 1496 | int l3 = SIMPLEX_4D[c] >= 1 ? 1 : 0; 1497 | 1498 | FN_DECIMAL x1 = x0 - i1 + G4; 1499 | FN_DECIMAL y1 = y0 - j1 + G4; 1500 | FN_DECIMAL z1 = z0 - k1 + G4; 1501 | FN_DECIMAL w1 = w0 - l1 + G4; 1502 | FN_DECIMAL x2 = x0 - i2 + 2 * G4; 1503 | FN_DECIMAL y2 = y0 - j2 + 2 * G4; 1504 | FN_DECIMAL z2 = z0 - k2 + 2 * G4; 1505 | FN_DECIMAL w2 = w0 - l2 + 2 * G4; 1506 | FN_DECIMAL x3 = x0 - i3 + 3 * G4; 1507 | FN_DECIMAL y3 = y0 - j3 + 3 * G4; 1508 | FN_DECIMAL z3 = z0 - k3 + 3 * G4; 1509 | FN_DECIMAL w3 = w0 - l3 + 3 * G4; 1510 | FN_DECIMAL x4 = x0 - 1 + 4 * G4; 1511 | FN_DECIMAL y4 = y0 - 1 + 4 * G4; 1512 | FN_DECIMAL z4 = z0 - 1 + 4 * G4; 1513 | FN_DECIMAL w4 = w0 - 1 + 4 * G4; 1514 | 1515 | t = (FN_DECIMAL)0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; 1516 | if (t < 0) n0 = 0; 1517 | else 1518 | { 1519 | t *= t; 1520 | n0 = t * t * GradCoord4D(seed, i, j, k, l, x0, y0, z0, w0); 1521 | } 1522 | t = (FN_DECIMAL)0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; 1523 | if (t < 0) n1 = 0; 1524 | else 1525 | { 1526 | t *= t; 1527 | n1 = t * t * GradCoord4D(seed, i + i1, j + j1, k + k1, l + l1, x1, y1, z1, w1); 1528 | } 1529 | t = (FN_DECIMAL)0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; 1530 | if (t < 0) n2 = 0; 1531 | else 1532 | { 1533 | t *= t; 1534 | n2 = t * t * GradCoord4D(seed, i + i2, j + j2, k + k2, l + l2, x2, y2, z2, w2); 1535 | } 1536 | t = (FN_DECIMAL)0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; 1537 | if (t < 0) n3 = 0; 1538 | else 1539 | { 1540 | t *= t; 1541 | n3 = t * t * GradCoord4D(seed, i + i3, j + j3, k + k3, l + l3, x3, y3, z3, w3); 1542 | } 1543 | t = (FN_DECIMAL)0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; 1544 | if (t < 0) n4 = 0; 1545 | else 1546 | { 1547 | t *= t; 1548 | n4 = t * t * GradCoord4D(seed, i + 1, j + 1, k + 1, l + 1, x4, y4, z4, w4); 1549 | } 1550 | 1551 | return 27 * (n0 + n1 + n2 + n3 + n4); 1552 | } 1553 | 1554 | // Cubic Noise 1555 | public FN_DECIMAL GetCubicFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1556 | { 1557 | x *= m_frequency; 1558 | y *= m_frequency; 1559 | z *= m_frequency; 1560 | 1561 | switch (m_fractalType) 1562 | { 1563 | case FractalType.FBM: 1564 | return SingleCubicFractalFBM(x, y, z); 1565 | case FractalType.Billow: 1566 | return SingleCubicFractalBillow(x, y, z); 1567 | case FractalType.RigidMulti: 1568 | return SingleCubicFractalRigidMulti(x, y, z); 1569 | default: 1570 | return 0; 1571 | } 1572 | } 1573 | 1574 | private FN_DECIMAL SingleCubicFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1575 | { 1576 | int seed = m_seed; 1577 | FN_DECIMAL sum = SingleCubic(seed, x, y, z); 1578 | FN_DECIMAL amp = 1; 1579 | int i = 0; 1580 | 1581 | while (++i < m_octaves) 1582 | { 1583 | x *= m_lacunarity; 1584 | y *= m_lacunarity; 1585 | z *= m_lacunarity; 1586 | 1587 | amp *= m_gain; 1588 | sum += SingleCubic(++seed, x, y, z) * amp; 1589 | } 1590 | 1591 | return sum * m_fractalBounding; 1592 | } 1593 | 1594 | private FN_DECIMAL SingleCubicFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1595 | { 1596 | int seed = m_seed; 1597 | FN_DECIMAL sum = Math.Abs(SingleCubic(seed, x, y, z)) * 2 - 1; 1598 | FN_DECIMAL amp = 1; 1599 | int i = 0; 1600 | 1601 | while (++i < m_octaves) 1602 | { 1603 | x *= m_lacunarity; 1604 | y *= m_lacunarity; 1605 | z *= m_lacunarity; 1606 | 1607 | amp *= m_gain; 1608 | sum += (Math.Abs(SingleCubic(++seed, x, y, z)) * 2 - 1) * amp; 1609 | } 1610 | 1611 | return sum * m_fractalBounding; 1612 | } 1613 | 1614 | private FN_DECIMAL SingleCubicFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1615 | { 1616 | int seed = m_seed; 1617 | FN_DECIMAL sum = 1 - Math.Abs(SingleCubic(seed, x, y, z)); 1618 | FN_DECIMAL amp = 1; 1619 | int i = 0; 1620 | 1621 | while (++i < m_octaves) 1622 | { 1623 | x *= m_lacunarity; 1624 | y *= m_lacunarity; 1625 | z *= m_lacunarity; 1626 | 1627 | amp *= m_gain; 1628 | sum -= (1 - Math.Abs(SingleCubic(++seed, x, y, z))) * amp; 1629 | } 1630 | 1631 | return sum; 1632 | } 1633 | 1634 | public FN_DECIMAL GetCubic(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1635 | { 1636 | return SingleCubic(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); 1637 | } 1638 | 1639 | private const FN_DECIMAL CUBIC_3D_BOUNDING = 1 / (FN_DECIMAL)(1.5 * 1.5 * 1.5); 1640 | 1641 | private FN_DECIMAL SingleCubic(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1642 | { 1643 | int x1 = FastFloor(x); 1644 | int y1 = FastFloor(y); 1645 | int z1 = FastFloor(z); 1646 | 1647 | int x0 = x1 - 1; 1648 | int y0 = y1 - 1; 1649 | int z0 = z1 - 1; 1650 | int x2 = x1 + 1; 1651 | int y2 = y1 + 1; 1652 | int z2 = z1 + 1; 1653 | int x3 = x1 + 2; 1654 | int y3 = y1 + 2; 1655 | int z3 = z1 + 2; 1656 | 1657 | FN_DECIMAL xs = x - (FN_DECIMAL)x1; 1658 | FN_DECIMAL ys = y - (FN_DECIMAL)y1; 1659 | FN_DECIMAL zs = z - (FN_DECIMAL)z1; 1660 | 1661 | return CubicLerp( 1662 | CubicLerp( 1663 | CubicLerp(ValCoord3D(seed, x0, y0, z0), ValCoord3D(seed, x1, y0, z0), ValCoord3D(seed, x2, y0, z0), ValCoord3D(seed, x3, y0, z0), xs), 1664 | CubicLerp(ValCoord3D(seed, x0, y1, z0), ValCoord3D(seed, x1, y1, z0), ValCoord3D(seed, x2, y1, z0), ValCoord3D(seed, x3, y1, z0), xs), 1665 | CubicLerp(ValCoord3D(seed, x0, y2, z0), ValCoord3D(seed, x1, y2, z0), ValCoord3D(seed, x2, y2, z0), ValCoord3D(seed, x3, y2, z0), xs), 1666 | CubicLerp(ValCoord3D(seed, x0, y3, z0), ValCoord3D(seed, x1, y3, z0), ValCoord3D(seed, x2, y3, z0), ValCoord3D(seed, x3, y3, z0), xs), 1667 | ys), 1668 | CubicLerp( 1669 | CubicLerp(ValCoord3D(seed, x0, y0, z1), ValCoord3D(seed, x1, y0, z1), ValCoord3D(seed, x2, y0, z1), ValCoord3D(seed, x3, y0, z1), xs), 1670 | CubicLerp(ValCoord3D(seed, x0, y1, z1), ValCoord3D(seed, x1, y1, z1), ValCoord3D(seed, x2, y1, z1), ValCoord3D(seed, x3, y1, z1), xs), 1671 | CubicLerp(ValCoord3D(seed, x0, y2, z1), ValCoord3D(seed, x1, y2, z1), ValCoord3D(seed, x2, y2, z1), ValCoord3D(seed, x3, y2, z1), xs), 1672 | CubicLerp(ValCoord3D(seed, x0, y3, z1), ValCoord3D(seed, x1, y3, z1), ValCoord3D(seed, x2, y3, z1), ValCoord3D(seed, x3, y3, z1), xs), 1673 | ys), 1674 | CubicLerp( 1675 | CubicLerp(ValCoord3D(seed, x0, y0, z2), ValCoord3D(seed, x1, y0, z2), ValCoord3D(seed, x2, y0, z2), ValCoord3D(seed, x3, y0, z2), xs), 1676 | CubicLerp(ValCoord3D(seed, x0, y1, z2), ValCoord3D(seed, x1, y1, z2), ValCoord3D(seed, x2, y1, z2), ValCoord3D(seed, x3, y1, z2), xs), 1677 | CubicLerp(ValCoord3D(seed, x0, y2, z2), ValCoord3D(seed, x1, y2, z2), ValCoord3D(seed, x2, y2, z2), ValCoord3D(seed, x3, y2, z2), xs), 1678 | CubicLerp(ValCoord3D(seed, x0, y3, z2), ValCoord3D(seed, x1, y3, z2), ValCoord3D(seed, x2, y3, z2), ValCoord3D(seed, x3, y3, z2), xs), 1679 | ys), 1680 | CubicLerp( 1681 | CubicLerp(ValCoord3D(seed, x0, y0, z3), ValCoord3D(seed, x1, y0, z3), ValCoord3D(seed, x2, y0, z3), ValCoord3D(seed, x3, y0, z3), xs), 1682 | CubicLerp(ValCoord3D(seed, x0, y1, z3), ValCoord3D(seed, x1, y1, z3), ValCoord3D(seed, x2, y1, z3), ValCoord3D(seed, x3, y1, z3), xs), 1683 | CubicLerp(ValCoord3D(seed, x0, y2, z3), ValCoord3D(seed, x1, y2, z3), ValCoord3D(seed, x2, y2, z3), ValCoord3D(seed, x3, y2, z3), xs), 1684 | CubicLerp(ValCoord3D(seed, x0, y3, z3), ValCoord3D(seed, x1, y3, z3), ValCoord3D(seed, x2, y3, z3), ValCoord3D(seed, x3, y3, z3), xs), 1685 | ys), 1686 | zs) * CUBIC_3D_BOUNDING; 1687 | } 1688 | 1689 | 1690 | public FN_DECIMAL GetCubicFractal(FN_DECIMAL x, FN_DECIMAL y) 1691 | { 1692 | x *= m_frequency; 1693 | y *= m_frequency; 1694 | 1695 | switch (m_fractalType) 1696 | { 1697 | case FractalType.FBM: 1698 | return SingleCubicFractalFBM(x, y); 1699 | case FractalType.Billow: 1700 | return SingleCubicFractalBillow(x, y); 1701 | case FractalType.RigidMulti: 1702 | return SingleCubicFractalRigidMulti(x, y); 1703 | default: 1704 | return 0; 1705 | } 1706 | } 1707 | 1708 | private FN_DECIMAL SingleCubicFractalFBM(FN_DECIMAL x, FN_DECIMAL y) 1709 | { 1710 | int seed = m_seed; 1711 | FN_DECIMAL sum = SingleCubic(seed, x, y); 1712 | FN_DECIMAL amp = 1; 1713 | int i = 0; 1714 | 1715 | while (++i < m_octaves) 1716 | { 1717 | x *= m_lacunarity; 1718 | y *= m_lacunarity; 1719 | 1720 | amp *= m_gain; 1721 | sum += SingleCubic(++seed, x, y) * amp; 1722 | } 1723 | 1724 | return sum * m_fractalBounding; 1725 | } 1726 | 1727 | private FN_DECIMAL SingleCubicFractalBillow(FN_DECIMAL x, FN_DECIMAL y) 1728 | { 1729 | int seed = m_seed; 1730 | FN_DECIMAL sum = Math.Abs(SingleCubic(seed, x, y)) * 2 - 1; 1731 | FN_DECIMAL amp = 1; 1732 | int i = 0; 1733 | 1734 | while (++i < m_octaves) 1735 | { 1736 | x *= m_lacunarity; 1737 | y *= m_lacunarity; 1738 | 1739 | amp *= m_gain; 1740 | sum += (Math.Abs(SingleCubic(++seed, x, y)) * 2 - 1) * amp; 1741 | } 1742 | 1743 | return sum * m_fractalBounding; 1744 | } 1745 | 1746 | private FN_DECIMAL SingleCubicFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) 1747 | { 1748 | int seed = m_seed; 1749 | FN_DECIMAL sum = 1 - Math.Abs(SingleCubic(seed, x, y)); 1750 | FN_DECIMAL amp = 1; 1751 | int i = 0; 1752 | 1753 | while (++i < m_octaves) 1754 | { 1755 | x *= m_lacunarity; 1756 | y *= m_lacunarity; 1757 | 1758 | amp *= m_gain; 1759 | sum -= (1 - Math.Abs(SingleCubic(++seed, x, y))) * amp; 1760 | } 1761 | 1762 | return sum; 1763 | } 1764 | 1765 | public FN_DECIMAL GetCubic(FN_DECIMAL x, FN_DECIMAL y) 1766 | { 1767 | x *= m_frequency; 1768 | y *= m_frequency; 1769 | 1770 | return SingleCubic(m_seed, x, y); 1771 | } 1772 | 1773 | private const FN_DECIMAL CUBIC_2D_BOUNDING = 1 / (FN_DECIMAL)(1.5 * 1.5); 1774 | 1775 | private FN_DECIMAL SingleCubic(int seed, FN_DECIMAL x, FN_DECIMAL y) 1776 | { 1777 | int x1 = FastFloor(x); 1778 | int y1 = FastFloor(y); 1779 | 1780 | int x0 = x1 - 1; 1781 | int y0 = y1 - 1; 1782 | int x2 = x1 + 1; 1783 | int y2 = y1 + 1; 1784 | int x3 = x1 + 2; 1785 | int y3 = y1 + 2; 1786 | 1787 | FN_DECIMAL xs = x - (FN_DECIMAL)x1; 1788 | FN_DECIMAL ys = y - (FN_DECIMAL)y1; 1789 | 1790 | return CubicLerp( 1791 | CubicLerp(ValCoord2D(seed, x0, y0), ValCoord2D(seed, x1, y0), ValCoord2D(seed, x2, y0), ValCoord2D(seed, x3, y0), 1792 | xs), 1793 | CubicLerp(ValCoord2D(seed, x0, y1), ValCoord2D(seed, x1, y1), ValCoord2D(seed, x2, y1), ValCoord2D(seed, x3, y1), 1794 | xs), 1795 | CubicLerp(ValCoord2D(seed, x0, y2), ValCoord2D(seed, x1, y2), ValCoord2D(seed, x2, y2), ValCoord2D(seed, x3, y2), 1796 | xs), 1797 | CubicLerp(ValCoord2D(seed, x0, y3), ValCoord2D(seed, x1, y3), ValCoord2D(seed, x2, y3), ValCoord2D(seed, x3, y3), 1798 | xs), 1799 | ys) * CUBIC_2D_BOUNDING; 1800 | } 1801 | 1802 | // Cellular Noise 1803 | public FN_DECIMAL GetCellular(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1804 | { 1805 | x *= m_frequency; 1806 | y *= m_frequency; 1807 | z *= m_frequency; 1808 | 1809 | switch (m_cellularReturnType) 1810 | { 1811 | case CellularReturnType.CellValue: 1812 | case CellularReturnType.NoiseLookup: 1813 | case CellularReturnType.Distance: 1814 | return SingleCellular(x, y, z); 1815 | default: 1816 | return SingleCellular2Edge(x, y, z); 1817 | } 1818 | } 1819 | 1820 | private FN_DECIMAL SingleCellular(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1821 | { 1822 | int xr = FastRound(x); 1823 | int yr = FastRound(y); 1824 | int zr = FastRound(z); 1825 | 1826 | FN_DECIMAL distance = 999999; 1827 | int xc = 0, yc = 0, zc = 0; 1828 | 1829 | switch (m_cellularDistanceFunction) 1830 | { 1831 | case CellularDistanceFunction.Euclidean: 1832 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1833 | { 1834 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1835 | { 1836 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1837 | { 1838 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1839 | 1840 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1841 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1842 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1843 | 1844 | FN_DECIMAL newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; 1845 | 1846 | if (newDistance < distance) 1847 | { 1848 | distance = newDistance; 1849 | xc = xi; 1850 | yc = yi; 1851 | zc = zi; 1852 | } 1853 | } 1854 | } 1855 | } 1856 | break; 1857 | case CellularDistanceFunction.Manhattan: 1858 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1859 | { 1860 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1861 | { 1862 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1863 | { 1864 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1865 | 1866 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1867 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1868 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1869 | 1870 | FN_DECIMAL newDistance = Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ); 1871 | 1872 | if (newDistance < distance) 1873 | { 1874 | distance = newDistance; 1875 | xc = xi; 1876 | yc = yi; 1877 | zc = zi; 1878 | } 1879 | } 1880 | } 1881 | } 1882 | break; 1883 | case CellularDistanceFunction.Natural: 1884 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1885 | { 1886 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1887 | { 1888 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1889 | { 1890 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1891 | 1892 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1893 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1894 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1895 | 1896 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ); 1897 | 1898 | if (newDistance < distance) 1899 | { 1900 | distance = newDistance; 1901 | xc = xi; 1902 | yc = yi; 1903 | zc = zi; 1904 | } 1905 | } 1906 | } 1907 | } 1908 | break; 1909 | } 1910 | 1911 | switch (m_cellularReturnType) 1912 | { 1913 | case CellularReturnType.CellValue: 1914 | return ValCoord3D(m_seed, xc, yc, zc); 1915 | 1916 | case CellularReturnType.NoiseLookup: 1917 | Float3 vec = CELL_3D[Hash3D(m_seed, xc, yc, zc) & 255]; 1918 | return m_cellularNoiseLookup.GetNoise(xc + vec.x * m_cellularJitter, yc + vec.y * m_cellularJitter, zc + vec.z * m_cellularJitter); 1919 | 1920 | case CellularReturnType.Distance: 1921 | return distance; 1922 | default: 1923 | return 0; 1924 | } 1925 | } 1926 | 1927 | private FN_DECIMAL SingleCellular2Edge(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1928 | { 1929 | int xr = FastRound(x); 1930 | int yr = FastRound(y); 1931 | int zr = FastRound(z); 1932 | 1933 | FN_DECIMAL[] distance = { 999999, 999999, 999999, 999999 }; 1934 | 1935 | switch (m_cellularDistanceFunction) 1936 | { 1937 | case CellularDistanceFunction.Euclidean: 1938 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1939 | { 1940 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1941 | { 1942 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1943 | { 1944 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1945 | 1946 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1947 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1948 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1949 | 1950 | FN_DECIMAL newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; 1951 | 1952 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 1953 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 1954 | distance[0] = Math.Min(distance[0], newDistance); 1955 | } 1956 | } 1957 | } 1958 | break; 1959 | case CellularDistanceFunction.Manhattan: 1960 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1961 | { 1962 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1963 | { 1964 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1965 | { 1966 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1967 | 1968 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1969 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1970 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1971 | 1972 | FN_DECIMAL newDistance = Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ); 1973 | 1974 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 1975 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 1976 | distance[0] = Math.Min(distance[0], newDistance); 1977 | } 1978 | } 1979 | } 1980 | break; 1981 | case CellularDistanceFunction.Natural: 1982 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1983 | { 1984 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1985 | { 1986 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1987 | { 1988 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1989 | 1990 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1991 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1992 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1993 | 1994 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ); 1995 | 1996 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 1997 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 1998 | distance[0] = Math.Min(distance[0], newDistance); 1999 | } 2000 | } 2001 | } 2002 | break; 2003 | default: 2004 | break; 2005 | } 2006 | 2007 | switch (m_cellularReturnType) 2008 | { 2009 | case CellularReturnType.Distance2: 2010 | return distance[m_cellularDistanceIndex1]; 2011 | case CellularReturnType.Distance2Add: 2012 | return distance[m_cellularDistanceIndex1] + distance[m_cellularDistanceIndex0]; 2013 | case CellularReturnType.Distance2Sub: 2014 | return distance[m_cellularDistanceIndex1] - distance[m_cellularDistanceIndex0]; 2015 | case CellularReturnType.Distance2Mul: 2016 | return distance[m_cellularDistanceIndex1] * distance[m_cellularDistanceIndex0]; 2017 | case CellularReturnType.Distance2Div: 2018 | return distance[m_cellularDistanceIndex0] / distance[m_cellularDistanceIndex1]; 2019 | default: 2020 | return 0; 2021 | } 2022 | } 2023 | 2024 | public FN_DECIMAL GetCellular(FN_DECIMAL x, FN_DECIMAL y) 2025 | { 2026 | x *= m_frequency; 2027 | y *= m_frequency; 2028 | 2029 | switch (m_cellularReturnType) 2030 | { 2031 | case CellularReturnType.CellValue: 2032 | case CellularReturnType.NoiseLookup: 2033 | case CellularReturnType.Distance: 2034 | return SingleCellular(x, y); 2035 | default: 2036 | return SingleCellular2Edge(x, y); 2037 | } 2038 | } 2039 | 2040 | private FN_DECIMAL SingleCellular(FN_DECIMAL x, FN_DECIMAL y) 2041 | { 2042 | int xr = FastRound(x); 2043 | int yr = FastRound(y); 2044 | 2045 | FN_DECIMAL distance = 999999; 2046 | int xc = 0, yc = 0; 2047 | 2048 | switch (m_cellularDistanceFunction) 2049 | { 2050 | default: 2051 | case CellularDistanceFunction.Euclidean: 2052 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2053 | { 2054 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2055 | { 2056 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2057 | 2058 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2059 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2060 | 2061 | FN_DECIMAL newDistance = vecX * vecX + vecY * vecY; 2062 | 2063 | if (newDistance < distance) 2064 | { 2065 | distance = newDistance; 2066 | xc = xi; 2067 | yc = yi; 2068 | } 2069 | } 2070 | } 2071 | break; 2072 | case CellularDistanceFunction.Manhattan: 2073 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2074 | { 2075 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2076 | { 2077 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2078 | 2079 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2080 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2081 | 2082 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY)); 2083 | 2084 | if (newDistance < distance) 2085 | { 2086 | distance = newDistance; 2087 | xc = xi; 2088 | yc = yi; 2089 | } 2090 | } 2091 | } 2092 | break; 2093 | case CellularDistanceFunction.Natural: 2094 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2095 | { 2096 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2097 | { 2098 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2099 | 2100 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2101 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2102 | 2103 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY)) + (vecX * vecX + vecY * vecY); 2104 | 2105 | if (newDistance < distance) 2106 | { 2107 | distance = newDistance; 2108 | xc = xi; 2109 | yc = yi; 2110 | } 2111 | } 2112 | } 2113 | break; 2114 | } 2115 | 2116 | switch (m_cellularReturnType) 2117 | { 2118 | case CellularReturnType.CellValue: 2119 | return ValCoord2D(m_seed, xc, yc); 2120 | 2121 | case CellularReturnType.NoiseLookup: 2122 | Float2 vec = CELL_2D[Hash2D(m_seed, xc, yc) & 255]; 2123 | return m_cellularNoiseLookup.GetNoise(xc + vec.x * m_cellularJitter, yc + vec.y * m_cellularJitter); 2124 | 2125 | case CellularReturnType.Distance: 2126 | return distance; 2127 | default: 2128 | return 0; 2129 | } 2130 | } 2131 | 2132 | private FN_DECIMAL SingleCellular2Edge(FN_DECIMAL x, FN_DECIMAL y) 2133 | { 2134 | int xr = FastRound(x); 2135 | int yr = FastRound(y); 2136 | 2137 | FN_DECIMAL[] distance = { 999999, 999999, 999999, 999999 }; 2138 | 2139 | switch (m_cellularDistanceFunction) 2140 | { 2141 | default: 2142 | case CellularDistanceFunction.Euclidean: 2143 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2144 | { 2145 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2146 | { 2147 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2148 | 2149 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2150 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2151 | 2152 | FN_DECIMAL newDistance = vecX * vecX + vecY * vecY; 2153 | 2154 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 2155 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 2156 | distance[0] = Math.Min(distance[0], newDistance); 2157 | } 2158 | } 2159 | break; 2160 | case CellularDistanceFunction.Manhattan: 2161 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2162 | { 2163 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2164 | { 2165 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2166 | 2167 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2168 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2169 | 2170 | FN_DECIMAL newDistance = Math.Abs(vecX) + Math.Abs(vecY); 2171 | 2172 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 2173 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 2174 | distance[0] = Math.Min(distance[0], newDistance); 2175 | } 2176 | } 2177 | break; 2178 | case CellularDistanceFunction.Natural: 2179 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2180 | { 2181 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2182 | { 2183 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2184 | 2185 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2186 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2187 | 2188 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY)) + (vecX * vecX + vecY * vecY); 2189 | 2190 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 2191 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 2192 | distance[0] = Math.Min(distance[0], newDistance); 2193 | } 2194 | } 2195 | break; 2196 | } 2197 | 2198 | switch (m_cellularReturnType) 2199 | { 2200 | case CellularReturnType.Distance2: 2201 | return distance[m_cellularDistanceIndex1]; 2202 | case CellularReturnType.Distance2Add: 2203 | return distance[m_cellularDistanceIndex1] + distance[m_cellularDistanceIndex0]; 2204 | case CellularReturnType.Distance2Sub: 2205 | return distance[m_cellularDistanceIndex1] - distance[m_cellularDistanceIndex0]; 2206 | case CellularReturnType.Distance2Mul: 2207 | return distance[m_cellularDistanceIndex1] * distance[m_cellularDistanceIndex0]; 2208 | case CellularReturnType.Distance2Div: 2209 | return distance[m_cellularDistanceIndex0] / distance[m_cellularDistanceIndex1]; 2210 | default: 2211 | return 0; 2212 | } 2213 | } 2214 | 2215 | public void GradientPerturb(ref FN_DECIMAL x, ref FN_DECIMAL y, ref FN_DECIMAL z) 2216 | { 2217 | SingleGradientPerturb(m_seed, m_gradientPerturbAmp, m_frequency, ref x, ref y, ref z); 2218 | } 2219 | 2220 | public void GradientPerturbFractal(ref FN_DECIMAL x, ref FN_DECIMAL y, ref FN_DECIMAL z) 2221 | { 2222 | int seed = m_seed; 2223 | FN_DECIMAL amp = m_gradientPerturbAmp * m_fractalBounding; 2224 | FN_DECIMAL freq = m_frequency; 2225 | 2226 | SingleGradientPerturb(seed, amp, m_frequency, ref x, ref y, ref z); 2227 | 2228 | for (int i = 1; i < m_octaves; i++) 2229 | { 2230 | freq *= m_lacunarity; 2231 | amp *= m_gain; 2232 | SingleGradientPerturb(++seed, amp, freq, ref x, ref y, ref z); 2233 | } 2234 | } 2235 | 2236 | private void SingleGradientPerturb(int seed, FN_DECIMAL perturbAmp, FN_DECIMAL frequency, ref FN_DECIMAL x, ref FN_DECIMAL y, ref FN_DECIMAL z) 2237 | { 2238 | FN_DECIMAL xf = x * frequency; 2239 | FN_DECIMAL yf = y * frequency; 2240 | FN_DECIMAL zf = z * frequency; 2241 | 2242 | int x0 = FastFloor(xf); 2243 | int y0 = FastFloor(yf); 2244 | int z0 = FastFloor(zf); 2245 | int x1 = x0 + 1; 2246 | int y1 = y0 + 1; 2247 | int z1 = z0 + 1; 2248 | 2249 | FN_DECIMAL xs, ys, zs; 2250 | switch (m_interp) 2251 | { 2252 | default: 2253 | case Interp.Linear: 2254 | xs = xf - x0; 2255 | ys = yf - y0; 2256 | zs = zf - z0; 2257 | break; 2258 | case Interp.Hermite: 2259 | xs = InterpHermiteFunc(xf - x0); 2260 | ys = InterpHermiteFunc(yf - y0); 2261 | zs = InterpHermiteFunc(zf - z0); 2262 | break; 2263 | case Interp.Quintic: 2264 | xs = InterpQuinticFunc(xf - x0); 2265 | ys = InterpQuinticFunc(yf - y0); 2266 | zs = InterpQuinticFunc(zf - z0); 2267 | break; 2268 | } 2269 | 2270 | Float3 vec0 = CELL_3D[Hash3D(seed, x0, y0, z0) & 255]; 2271 | Float3 vec1 = CELL_3D[Hash3D(seed, x1, y0, z0) & 255]; 2272 | 2273 | FN_DECIMAL lx0x = Lerp(vec0.x, vec1.x, xs); 2274 | FN_DECIMAL ly0x = Lerp(vec0.y, vec1.y, xs); 2275 | FN_DECIMAL lz0x = Lerp(vec0.z, vec1.z, xs); 2276 | 2277 | vec0 = CELL_3D[Hash3D(seed, x0, y1, z0) & 255]; 2278 | vec1 = CELL_3D[Hash3D(seed, x1, y1, z0) & 255]; 2279 | 2280 | FN_DECIMAL lx1x = Lerp(vec0.x, vec1.x, xs); 2281 | FN_DECIMAL ly1x = Lerp(vec0.y, vec1.y, xs); 2282 | FN_DECIMAL lz1x = Lerp(vec0.z, vec1.z, xs); 2283 | 2284 | FN_DECIMAL lx0y = Lerp(lx0x, lx1x, ys); 2285 | FN_DECIMAL ly0y = Lerp(ly0x, ly1x, ys); 2286 | FN_DECIMAL lz0y = Lerp(lz0x, lz1x, ys); 2287 | 2288 | vec0 = CELL_3D[Hash3D(seed, x0, y0, z1) & 255]; 2289 | vec1 = CELL_3D[Hash3D(seed, x1, y0, z1) & 255]; 2290 | 2291 | lx0x = Lerp(vec0.x, vec1.x, xs); 2292 | ly0x = Lerp(vec0.y, vec1.y, xs); 2293 | lz0x = Lerp(vec0.z, vec1.z, xs); 2294 | 2295 | vec0 = CELL_3D[Hash3D(seed, x0, y1, z1) & 255]; 2296 | vec1 = CELL_3D[Hash3D(seed, x1, y1, z1) & 255]; 2297 | 2298 | lx1x = Lerp(vec0.x, vec1.x, xs); 2299 | ly1x = Lerp(vec0.y, vec1.y, xs); 2300 | lz1x = Lerp(vec0.z, vec1.z, xs); 2301 | 2302 | x += Lerp(lx0y, Lerp(lx0x, lx1x, ys), zs) * perturbAmp; 2303 | y += Lerp(ly0y, Lerp(ly0x, ly1x, ys), zs) * perturbAmp; 2304 | z += Lerp(lz0y, Lerp(lz0x, lz1x, ys), zs) * perturbAmp; 2305 | } 2306 | 2307 | public void GradientPerturb(ref FN_DECIMAL x, ref FN_DECIMAL y) 2308 | { 2309 | SingleGradientPerturb(m_seed, m_gradientPerturbAmp, m_frequency, ref x, ref y); 2310 | } 2311 | 2312 | public void GradientPerturbFractal(ref FN_DECIMAL x, ref FN_DECIMAL y) 2313 | { 2314 | int seed = m_seed; 2315 | FN_DECIMAL amp = m_gradientPerturbAmp * m_fractalBounding; 2316 | FN_DECIMAL freq = m_frequency; 2317 | 2318 | SingleGradientPerturb(seed, amp, m_frequency, ref x, ref y); 2319 | 2320 | for (int i = 1; i < m_octaves; i++) 2321 | { 2322 | freq *= m_lacunarity; 2323 | amp *= m_gain; 2324 | SingleGradientPerturb(++seed, amp, freq, ref x, ref y); 2325 | } 2326 | } 2327 | 2328 | private void SingleGradientPerturb(int seed, FN_DECIMAL perturbAmp, FN_DECIMAL frequency, ref FN_DECIMAL x, ref FN_DECIMAL y) 2329 | { 2330 | FN_DECIMAL xf = x * frequency; 2331 | FN_DECIMAL yf = y * frequency; 2332 | 2333 | int x0 = FastFloor(xf); 2334 | int y0 = FastFloor(yf); 2335 | int x1 = x0 + 1; 2336 | int y1 = y0 + 1; 2337 | 2338 | FN_DECIMAL xs, ys; 2339 | switch (m_interp) 2340 | { 2341 | default: 2342 | case Interp.Linear: 2343 | xs = xf - x0; 2344 | ys = yf - y0; 2345 | break; 2346 | case Interp.Hermite: 2347 | xs = InterpHermiteFunc(xf - x0); 2348 | ys = InterpHermiteFunc(yf - y0); 2349 | break; 2350 | case Interp.Quintic: 2351 | xs = InterpQuinticFunc(xf - x0); 2352 | ys = InterpQuinticFunc(yf - y0); 2353 | break; 2354 | } 2355 | 2356 | Float2 vec0 = CELL_2D[Hash2D(seed, x0, y0) & 255]; 2357 | Float2 vec1 = CELL_2D[Hash2D(seed, x1, y0) & 255]; 2358 | 2359 | FN_DECIMAL lx0x = Lerp(vec0.x, vec1.x, xs); 2360 | FN_DECIMAL ly0x = Lerp(vec0.y, vec1.y, xs); 2361 | 2362 | vec0 = CELL_2D[Hash2D(seed, x0, y1) & 255]; 2363 | vec1 = CELL_2D[Hash2D(seed, x1, y1) & 255]; 2364 | 2365 | FN_DECIMAL lx1x = Lerp(vec0.x, vec1.x, xs); 2366 | FN_DECIMAL ly1x = Lerp(vec0.y, vec1.y, xs); 2367 | 2368 | x += Lerp(lx0x, lx1x, ys) * perturbAmp; 2369 | y += Lerp(ly0x, ly1x, ys) * perturbAmp; 2370 | } 2371 | 2372 | } 2373 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Jordan Peck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![discord](https://img.shields.io/discord/703636892901441577?style=flat-square&logo=discord "Discord")](https://discord.gg/SHVaVfV) 2 | 3 | ### Depreciated 4 | This version of FastNoise is now depreciated, please look into using [FastNoise Lite](https://github.com/Auburn/FastNoise/) which is the successor to this library. 5 | 6 | # FastNoise 7 | 8 | This is the C# version of [FastNoise](https://github.com/Auburns/FastNoise) 9 | 10 | FastNoise is an open source noise generation library with a large collection of different noise algorithms. This library has been designed for realtime usage from the ground up, so has been optimised for speed without sacrificing noise quality. 11 | 12 | This project started when my search to find a good noise library for procedural terrain generation concluded without an obvious choice. I enjoyed the options and customisation of Accidental Noise Library and the speed of LibNoise, so many of the techniques from these libraries and the knowledge I gained from reading through their source has gone into creating FastNoise. 13 | 14 | I have now also created [FastNoise SIMD](https://github.com/Auburns/FastNoiseSIMD), which utilises SIMD CPU instructions to gain huge performance boosts. It is slightly less flexible and cannot be converted to other languages, but if you can I would highly suggest using this for heavy noise generation loads. 15 | 16 | ### Features 17 | - Value Noise 2D, 3D 18 | - Perlin Noise 2D, 3D 19 | - Simplex Noise 2D, 3D, 4D 20 | - Cubic Noise 2D, 3D 21 | - Gradient Perturb 2D, 3D 22 | - Multiple fractal options for all of the above 23 | - Cellular (Voronoi) Noise 2D, 3D 24 | - White Noise 2D, 3D, 4D 25 | - Supports floats or doubles 26 | 27 | ### Wiki 28 | Usage and documentation available in wiki 29 | 30 | [Wiki Link](https://github.com/Auburns/FastNoise/wiki) 31 | 32 | ### Related repositories 33 | - [FastNoise Java](https://github.com/Auburns/FastNoise_Java) 34 | - [FastNoise SIMD](https://github.com/Auburns/FastNoiseSIMD) 35 | - [FastNoise Unity](https://www.assetstore.unity3d.com/en/#!/content/70706) 36 | - [Unreal FastNoise](https://github.com/midgen/UnrealFastNoise) 37 | 38 | Credit to [CubicNoise](https://github.com/jobtalle/CubicNoise) for the cubic noise algorithm 39 | 40 | ## FastNoise Preview 41 | 42 | I have written a compact testing application for all the features included in FastNoise with a visual representation. I use this for development purposes and testing noise settings used in terrain generation. 43 | 44 | Download links can be found in the [Releases Section](https://github.com/Auburns/FastNoise/releases). 45 | 46 | ![FastNoise Preview](http://i.imgur.com/uG7Vepc.png) 47 | 48 | 49 | # Performance Comparisons 50 | Benchmarking done on C++ version. 51 | 52 | Using default noise settings on FastNoise and matching those settings across the other libraries where possible. 53 | 54 | Timings below are x1000 ns to generate 32x32x32 points of noise on a single thread. 55 | 56 | - CPU: Intel Xeon Skylake @ 2.0Ghz 57 | - Compiler: Intel 17.0 x64 58 | 59 | | Noise Type |FastNoise | FastNoiseSIMD AVX2 | LibNoise | FastNoise 2D | 60 | |-------------|----------|--------------------|-----------|--------------| 61 | | White Noise |141 | 13 | | 111 | 62 | | Value |635 | 160 | | 364 | 63 | | Perlin |964 | 342 | 1409 | 476 | 64 | | Simplex |1189 | 340 | | 875 | 65 | | Cellular |2933 | 1472 | 56960 | 1074 | 66 | | Cubic |2933 | 1393 | | 872 | 67 | 68 | Comparision of fractal performance [here](https://github.com/Auburns/FastNoiseSIMD/wiki/In-depth-SIMD-level). 69 | 70 | # Examples 71 | ## Cellular Noise 72 | ![Cellular Noise](http://i.imgur.com/quAic8M.png) 73 | 74 | ![Cellular Noise](http://i.imgur.com/gAd9Y2t.png) 75 | 76 | ![Cellular Noise](http://i.imgur.com/7kJd4fA.png) 77 | 78 | ## Fractal Noise 79 | ![Fractal Noise](http://i.imgur.com/XqSD7eR.png) 80 | 81 | ## Value Noise 82 | ![Value Noise](http://i.imgur.com/X2lbFZR.png) 83 | 84 | ## White Noise 85 | ![White Noise](http://i.imgur.com/QIlYvyQ.png) 86 | 87 | ## Gradient Perturb 88 | ![Gradient Perturb](http://i.imgur.com/gOjc1u1.png) 89 | 90 | ![Gradient Perturb](http://i.imgur.com/ui045Bk.png) 91 | 92 | ![Gradient Perturb](http://i.imgur.com/JICFypT.png) 93 | 94 | # Any suggestions or questions welcome 95 | --------------------------------------------------------------------------------