├── README.md └── [1]MarchingCube ├── GPU ├── WenzyMarchingGPU.cs ├── Noise.compute ├── WenzyMarchingShader.compute └── WenzyMarchTables.compute ├── MarchingCube.unity └── CPU ├── WenzyMarchingCubeCPU.cs └── FastNoise.cs /README.md: -------------------------------------------------------------------------------- 1 | # Marching-cube-in-Unity 2 | 3 | 4 | Here are some source code about marching cubes on Github.(Have tested in Unity2018 and Unity2019) 5 | 6 | It includes two version(CPU and GPU) ,which is the foundation of my Test417(https://twitter.com/i/status/1220778085798137856) and 7 | Test440(https://twitter.com/i/status/1169084756908105729). 8 | Any ideas to optimize the GPU version is really appreciate. 9 | 10 | * Performance: In Gpu version ,run 80 * 80 * 80 voxel at 80 fps in average. 11 | 12 | * Recommend link 13 | * https://www.youtube.com/watch?v=M3iI2l0ltbE 14 | * http://paulbourke.net/geometry/polygonise/ 15 | 16 | 17 | The scene include two main scripts,can easily assign different material to acheive different effect.The gif has assigned a SSS material for testing. 18 | 19 | ![](https://media.giphy.com/media/QX1wUoQwqGlqxvEhW5/giphy.gif) 20 | 21 | -------------------------------------------------------------------------------- /[1]MarchingCube/GPU/WenzyMarchingGPU.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class WenzyMarchingGPU : MonoBehaviour 6 | { 7 | public ComputeShader marchingCS; 8 | int kernel; 9 | int maxTriNum; 10 | 11 | public struct Triangles 12 | { 13 | public Vector3 posA, posB, posC; 14 | public Vector3 normalA, normalB, normalC; 15 | } 16 | 17 | RenderTexture VoxelTexture; 18 | public ComputeBuffer Tribuffer; 19 | public ComputeBuffer PosBuffer,NormalBuffer,IndexBuffer; 20 | public ComputeBuffer CountBuffer; 21 | 22 | Mesh mesh; 23 | [Header("Marching cube feature")] 24 | public Vector3 CenterPos; 25 | public bool EnableSmooth; 26 | public Material mat; 27 | public int GridRes = 8; // usually the gridres must be the multiples of 8 28 | public float GridW = 2f; 29 | [Header("Animation")] 30 | public float NoiseInterval = 0.05f; 31 | public float IsoLevel = 0.5f; 32 | 33 | void Start() 34 | { 35 | VoxelTexture = new RenderTexture(GridRes, GridRes, 0,RenderTextureFormat.RFloat); 36 | VoxelTexture.enableRandomWrite = true; 37 | VoxelTexture.dimension = UnityEngine.Rendering.TextureDimension.Tex3D; 38 | VoxelTexture.volumeDepth = GridRes; 39 | VoxelTexture.filterMode = FilterMode.Point; 40 | VoxelTexture.wrapMode = TextureWrapMode.Repeat; 41 | VoxelTexture.useMipMap = false; 42 | VoxelTexture.Create(); 43 | 44 | gameObject.AddComponent(); 45 | gameObject.AddComponent().material = mat; 46 | mesh = GetComponent().mesh; 47 | mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; 48 | 49 | 50 | maxTriNum = GridRes * GridRes * GridRes * 5; // the max triangle num 51 | 52 | int maxValue = maxTriNum; 53 | Tribuffer = new ComputeBuffer(maxValue, sizeof(float) * 3 * 3 * 2, ComputeBufferType.Append); 54 | PosBuffer = new ComputeBuffer(maxValue * 3, sizeof(float) * 3 * 3, ComputeBufferType.Default); 55 | NormalBuffer = new ComputeBuffer(maxValue * 3, sizeof(float) * 3 * 3, ComputeBufferType.Default); 56 | IndexBuffer = new ComputeBuffer(maxValue * 3, sizeof(int) * 3, ComputeBufferType.Default); 57 | CountBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw); 58 | } 59 | 60 | void UpdateMesh() 61 | { 62 | Tribuffer.SetCounterValue(0); 63 | 64 | // common 65 | marchingCS.SetInt("GridRes", GridRes); 66 | marchingCS.SetFloat("Time", Time.time); 67 | marchingCS.SetFloat("NoiseInterval", NoiseInterval); 68 | marchingCS.SetFloat("IsoLevel", IsoLevel); 69 | marchingCS.SetBool("EnableSmooth", EnableSmooth); 70 | marchingCS.SetVector("CenterPos", CenterPos); 71 | marchingCS.SetFloat("GridW", GridW); 72 | 73 | kernel = marchingCS.FindKernel("UpdateVoxel"); 74 | marchingCS.SetTexture(kernel, "VoxelTexture", VoxelTexture); 75 | marchingCS.Dispatch(kernel, GridRes, GridRes, GridRes); 76 | 77 | kernel = marchingCS.FindKernel("CalculateTriangle"); 78 | marchingCS.SetTexture(kernel, "VoxelTexture", VoxelTexture); 79 | marchingCS.SetBuffer(kernel, "Tribuffer", Tribuffer); 80 | marchingCS.Dispatch(kernel, GridRes/8, GridRes/8, GridRes/8); 81 | 82 | ComputeBuffer.CopyCount(Tribuffer, CountBuffer, 0); 83 | int[] countArr = { 0 }; 84 | CountBuffer.GetData(countArr); 85 | int count = countArr[0]; // the actual num 86 | 87 | if (count != 0) 88 | { 89 | kernel = marchingCS.FindKernel("ExtractData"); 90 | marchingCS.SetInt("TriangleCount", count); 91 | marchingCS.SetBuffer(kernel, "NewTriBuffer", Tribuffer); 92 | marchingCS.SetBuffer(kernel, "PosBuffer", PosBuffer); 93 | marchingCS.SetBuffer(kernel, "NormalBuffer", NormalBuffer); 94 | marchingCS.SetBuffer(kernel, "IndexBuffer", IndexBuffer); 95 | marchingCS.Dispatch(kernel, (int)Mathf.Ceil(count / 10f), 1, 1); 96 | } 97 | 98 | Vector3[] posArr = new Vector3[count * 3]; 99 | PosBuffer.GetData(posArr, 0, 0, count * 3); 100 | Vector3[] normalArr = new Vector3[count * 3]; 101 | NormalBuffer.GetData(normalArr, 0, 0, count * 3); 102 | 103 | 104 | int[] indexArr = new int[count * 3]; 105 | IndexBuffer.GetData(indexArr, 0, 0, count * 3); 106 | 107 | mesh.Clear(); 108 | mesh.vertices = posArr; 109 | mesh.normals = normalArr; 110 | mesh.triangles = indexArr; 111 | } 112 | 113 | void Update() 114 | { 115 | UpdateMesh(); 116 | } 117 | 118 | private void OnDisable() 119 | { 120 | Tribuffer.Release(); 121 | Tribuffer.Dispose(); 122 | PosBuffer.Release(); 123 | PosBuffer.Dispose(); 124 | NormalBuffer.Release(); 125 | NormalBuffer.Dispose(); 126 | IndexBuffer.Release(); 127 | IndexBuffer.Dispose(); 128 | CountBuffer.Release(); 129 | CountBuffer.Dispose(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /[1]MarchingCube/GPU/Noise.compute: -------------------------------------------------------------------------------- 1 | // Noise Shader Library for Unity - https://github.com/keijiro/NoiseShader 2 | // 3 | // Original work (webgl-noise) Copyright (C) 2011 Ashima Arts. 4 | // Translation and modification was made by Keijiro Takahashi. 5 | // 6 | // This shader is based on the webgl-noise GLSL shader. For further details 7 | // of the original shader, please see the following description from the 8 | // original source code. 9 | // 10 | 11 | // 12 | // Description : Array and textureless GLSL 2D/3D/4D simplex 13 | // noise functions. 14 | // Author : Ian McEwan, Ashima Arts. 15 | // Maintainer : ijm 16 | // Lastmod : 20110822 (ijm) 17 | // License : Copyright (C) 2011 Ashima Arts. All rights reserved. 18 | // Distributed under the MIT License. See LICENSE file. 19 | // https://github.com/ashima/webgl-noise 20 | // 21 | 22 | float3 mod289(float3 x) 23 | { 24 | return x - floor(x / 289.0) * 289.0; 25 | } 26 | 27 | float4 mod289(float4 x) 28 | { 29 | return x - floor(x / 289.0) * 289.0; 30 | } 31 | 32 | float4 permute(float4 x) 33 | { 34 | return mod289((x * 34.0 + 1.0) * x); 35 | } 36 | 37 | float4 taylorInvSqrt(float4 r) 38 | { 39 | return 1.79284291400159 - r * 0.85373472095314; 40 | } 41 | 42 | float snoise(float3 v) 43 | { 44 | const float2 C = float2(1.0 / 6.0, 1.0 / 3.0); 45 | 46 | // First corner 47 | float3 i = floor(v + dot(v, C.yyy)); 48 | float3 x0 = v - i + dot(i, C.xxx); 49 | 50 | // Other corners 51 | float3 g = step(x0.yzx, x0.xyz); 52 | float3 l = 1.0 - g; 53 | float3 i1 = min(g.xyz, l.zxy); 54 | float3 i2 = max(g.xyz, l.zxy); 55 | 56 | // x1 = x0 - i1 + 1.0 * C.xxx; 57 | // x2 = x0 - i2 + 2.0 * C.xxx; 58 | // x3 = x0 - 1.0 + 3.0 * C.xxx; 59 | float3 x1 = x0 - i1 + C.xxx; 60 | float3 x2 = x0 - i2 + C.yyy; 61 | float3 x3 = x0 - 0.5; 62 | 63 | // Permutations 64 | i = mod289(i); // Avoid truncation effects in permutation 65 | float4 p = 66 | permute(permute(permute(i.z + float4(0.0, i1.z, i2.z, 1.0)) 67 | + i.y + float4(0.0, i1.y, i2.y, 1.0)) 68 | + i.x + float4(0.0, i1.x, i2.x, 1.0)); 69 | 70 | // Gradients: 7x7 points over a square, mapped onto an octahedron. 71 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 72 | float4 j = p - 49.0 * floor(p / 49.0); // mod(p,7*7) 73 | 74 | float4 x_ = floor(j / 7.0); 75 | float4 y_ = floor(j - 7.0 * x_); // mod(j,N) 76 | 77 | float4 x = (x_ * 2.0 + 0.5) / 7.0 - 1.0; 78 | float4 y = (y_ * 2.0 + 0.5) / 7.0 - 1.0; 79 | 80 | float4 h = 1.0 - abs(x) - abs(y); 81 | 82 | float4 b0 = float4(x.xy, y.xy); 83 | float4 b1 = float4(x.zw, y.zw); 84 | 85 | //float4 s0 = float4(lessThan(b0, 0.0)) * 2.0 - 1.0; 86 | //float4 s1 = float4(lessThan(b1, 0.0)) * 2.0 - 1.0; 87 | float4 s0 = floor(b0) * 2.0 + 1.0; 88 | float4 s1 = floor(b1) * 2.0 + 1.0; 89 | float4 sh = -step(h, 0.0); 90 | 91 | float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; 92 | float4 a1 = b1.xzyw + s1.xzyw * sh.zzww; 93 | 94 | float3 g0 = float3(a0.xy, h.x); 95 | float3 g1 = float3(a0.zw, h.y); 96 | float3 g2 = float3(a1.xy, h.z); 97 | float3 g3 = float3(a1.zw, h.w); 98 | 99 | // Normalise gradients 100 | float4 norm = taylorInvSqrt(float4(dot(g0, g0), dot(g1, g1), dot(g2, g2), dot(g3, g3))); 101 | g0 *= norm.x; 102 | g1 *= norm.y; 103 | g2 *= norm.z; 104 | g3 *= norm.w; 105 | 106 | // Mix final noise value 107 | float4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0); 108 | m = m * m; 109 | m = m * m; 110 | 111 | float4 px = float4(dot(x0, g0), dot(x1, g1), dot(x2, g2), dot(x3, g3)); 112 | return 42.0 * dot(m, px); 113 | } 114 | 115 | float4 snoise_grad(float3 v) 116 | { 117 | const float2 C = float2(1.0 / 6.0, 1.0 / 3.0); 118 | 119 | // First corner 120 | float3 i = floor(v + dot(v, C.yyy)); 121 | float3 x0 = v - i + dot(i, C.xxx); 122 | 123 | // Other corners 124 | float3 g = step(x0.yzx, x0.xyz); 125 | float3 l = 1.0 - g; 126 | float3 i1 = min(g.xyz, l.zxy); 127 | float3 i2 = max(g.xyz, l.zxy); 128 | 129 | // x1 = x0 - i1 + 1.0 * C.xxx; 130 | // x2 = x0 - i2 + 2.0 * C.xxx; 131 | // x3 = x0 - 1.0 + 3.0 * C.xxx; 132 | float3 x1 = x0 - i1 + C.xxx; 133 | float3 x2 = x0 - i2 + C.yyy; 134 | float3 x3 = x0 - 0.5; 135 | 136 | // Permutations 137 | i = mod289(i); // Avoid truncation effects in permutation 138 | float4 p = 139 | permute(permute(permute(i.z + float4(0.0, i1.z, i2.z, 1.0)) 140 | + i.y + float4(0.0, i1.y, i2.y, 1.0)) 141 | + i.x + float4(0.0, i1.x, i2.x, 1.0)); 142 | 143 | // Gradients: 7x7 points over a square, mapped onto an octahedron. 144 | // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 145 | float4 j = p - 49.0 * floor(p / 49.0); // mod(p,7*7) 146 | 147 | float4 x_ = floor(j / 7.0); 148 | float4 y_ = floor(j - 7.0 * x_); // mod(j,N) 149 | 150 | float4 x = (x_ * 2.0 + 0.5) / 7.0 - 1.0; 151 | float4 y = (y_ * 2.0 + 0.5) / 7.0 - 1.0; 152 | 153 | float4 h = 1.0 - abs(x) - abs(y); 154 | 155 | float4 b0 = float4(x.xy, y.xy); 156 | float4 b1 = float4(x.zw, y.zw); 157 | 158 | //float4 s0 = float4(lessThan(b0, 0.0)) * 2.0 - 1.0; 159 | //float4 s1 = float4(lessThan(b1, 0.0)) * 2.0 - 1.0; 160 | float4 s0 = floor(b0) * 2.0 + 1.0; 161 | float4 s1 = floor(b1) * 2.0 + 1.0; 162 | float4 sh = -step(h, 0.0); 163 | 164 | float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; 165 | float4 a1 = b1.xzyw + s1.xzyw * sh.zzww; 166 | 167 | float3 g0 = float3(a0.xy, h.x); 168 | float3 g1 = float3(a0.zw, h.y); 169 | float3 g2 = float3(a1.xy, h.z); 170 | float3 g3 = float3(a1.zw, h.w); 171 | 172 | // Normalise gradients 173 | float4 norm = taylorInvSqrt(float4(dot(g0, g0), dot(g1, g1), dot(g2, g2), dot(g3, g3))); 174 | g0 *= norm.x; 175 | g1 *= norm.y; 176 | g2 *= norm.z; 177 | g3 *= norm.w; 178 | 179 | // Compute noise and gradient at P 180 | float4 m = max(0.6 - float4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0); 181 | float4 m2 = m * m; 182 | float4 m3 = m2 * m; 183 | float4 m4 = m2 * m2; 184 | float3 grad = 185 | -6.0 * m3.x * x0 * dot(x0, g0) + m4.x * g0 + 186 | -6.0 * m3.y * x1 * dot(x1, g1) + m4.y * g1 + 187 | -6.0 * m3.z * x2 * dot(x2, g2) + m4.z * g2 + 188 | -6.0 * m3.w * x3 * dot(x3, g3) + m4.w * g3; 189 | float4 px = float4(dot(x0, g0), dot(x1, g1), dot(x2, g2), dot(x3, g3)); 190 | return 42.0 * float4(grad, dot(m4, px)); 191 | } -------------------------------------------------------------------------------- /[1]MarchingCube/GPU/WenzyMarchingShader.compute: -------------------------------------------------------------------------------- 1 | #include "WenzyMarchTables.compute" 2 | #include "Noise.compute" 3 | 4 | #pragma kernel CalculateTriangle 5 | #pragma kernel UpdateVoxel 6 | #pragma kernel ExtractData 7 | 8 | struct Triangles { 9 | float3 posA, posB, posC; 10 | float3 normalA, normalB, normalC; 11 | }; 12 | 13 | RWTexture3D VoxelTexture; 14 | int GridRes; 15 | float Time; 16 | float NoiseInterval; 17 | float IsoLevel; 18 | bool EnableSmooth; 19 | float3 CenterPos; 20 | float GridW; 21 | int TriangleCount; 22 | 23 | 24 | float Random(float2 st) 25 | { 26 | return frac(sin(dot(st.xy, float2(12.9898, 78.233)))* 43758.5453123); 27 | } 28 | 29 | [numthreads(1, 1, 1)] 30 | void UpdateVoxel(uint3 id : SV_DispatchThreadID) { 31 | VoxelTexture[id.xyz] = (snoise((float3(id.xyz) + float3(Time, 0, 0))* NoiseInterval) + 1.0)/2.0; 32 | } 33 | 34 | RWStructuredBuffer PosBuffer, NormalBuffer; 35 | RWStructuredBuffer IndexBuffer; 36 | RWStructuredBuffer NewTriBuffer; 37 | AppendStructuredBuffer Tribuffer; 38 | 39 | [numthreads(10, 1, 1)] 40 | void ExtractData(uint3 id : SV_DispatchThreadID) { 41 | if (id.x < TriangleCount) { 42 | PosBuffer[id.x * 3] = NewTriBuffer[id.x].posA; 43 | PosBuffer[id.x * 3 + 1] = NewTriBuffer[id.x].posB; 44 | PosBuffer[id.x * 3 + 2] = NewTriBuffer[id.x].posC; 45 | NormalBuffer[id.x * 3] = NewTriBuffer[id.x].normalA; 46 | NormalBuffer[id.x * 3 + 1] = NewTriBuffer[id.x].normalB; 47 | NormalBuffer[id.x * 3 + 2] = NewTriBuffer[id.x].normalC; 48 | IndexBuffer[id.x * 3] = id.x * 3; 49 | IndexBuffer[id.x * 3 + 1] = id.x * 3 + 1; 50 | IndexBuffer[id.x * 3 + 2] = id.x * 3 + 2; 51 | } 52 | } 53 | 54 | [numthreads(8, 8, 8)] 55 | void CalculateTriangle(uint3 id : SV_DispatchThreadID) 56 | { 57 | float valCollection[8]; 58 | valCollection[0] = VoxelTexture[id.xyz + uint3(0, 0, 1)]; 59 | valCollection[1] = VoxelTexture[id.xyz + uint3(1, 0, 1)]; 60 | valCollection[2] = VoxelTexture[id.xyz + uint3(1, 0, 0)]; 61 | valCollection[3] = VoxelTexture[id.xyz + uint3(0, 0, 0)]; 62 | valCollection[4] = VoxelTexture[id.xyz + uint3(0, 1, 1)]; // 4 63 | valCollection[5] = VoxelTexture[id.xyz + uint3(1, 1, 1)]; // 5 64 | valCollection[6] = VoxelTexture[id.xyz + uint3(1, 1, 0)]; // 6 65 | valCollection[7] = VoxelTexture[id.xyz + uint3(0, 1, 0)]; // 7 66 | 67 | int index = 0; 68 | for (int l = 0; l < 8; l++) 69 | { 70 | if (valCollection[l] > IsoLevel) 71 | index |= 1 << l; 72 | } 73 | 74 | float3 dirOffset, finalPos,finalNormal,centerOffset; 75 | float voxelW = GridW / GridRes; 76 | 77 | centerOffset = float3(id.xyz) * voxelW + CenterPos - float3(1,1,1) * GridW / 2; 78 | int connectIndex1, connectIndex2; 79 | double lerpRatio; 80 | 81 | 82 | float3 p1, p2; 83 | 84 | for (int l = 0; l < 5; l++) 85 | { 86 | if (TriangleTable[index][l * 3] >= 0) 87 | { 88 | Triangles tempTri; 89 | for (int k = 0; k < 3; k++) { 90 | int newIndex = l * 3 + k; 91 | dirOffset.x = EdgePointDir[TriangleTable[index][newIndex]][0]; 92 | dirOffset.y = EdgePointDir[TriangleTable[index][newIndex]][1]; 93 | dirOffset.z = EdgePointDir[TriangleTable[index][newIndex]][2]; 94 | 95 | connectIndex1 = ConnectionMap[TriangleTable[index][newIndex]][0]; 96 | connectIndex2 = ConnectionMap[TriangleTable[index][newIndex]][1]; 97 | 98 | p1.x = VertexPointDir[connectIndex1][0]; 99 | p1.y = VertexPointDir[connectIndex1][1]; 100 | p1.z = VertexPointDir[connectIndex1][2]; 101 | 102 | p2.x = VertexPointDir[connectIndex2][0]; 103 | p2.y = VertexPointDir[connectIndex2][1]; 104 | p2.z = VertexPointDir[connectIndex2][2]; 105 | 106 | p1 *= voxelW; 107 | p2 *= voxelW; 108 | 109 | p1 /= 2.0f; 110 | p2 /= 2.0f; 111 | // 根据论文的公式计算插值 112 | finalPos = p1 + (IsoLevel - valCollection[connectIndex1]) * (p2 - p1) / (valCollection[connectIndex2] - valCollection[connectIndex1]); 113 | lerpRatio = distance(p1, finalPos) / distance(p1, p2); 114 | finalPos += centerOffset; 115 | 116 | if (k == 0) { 117 | tempTri.posC = finalPos; 118 | } 119 | else if (k == 1) { 120 | tempTri.posB = finalPos; 121 | } 122 | else if (k == 2) { 123 | tempTri.posA = finalPos; 124 | } 125 | 126 | float3 normal1, normal2; 127 | if (EnableSmooth) { 128 | 129 | normal1.x = VoxelTexture[id.xyz + uint3(IndexMap[connectIndex1][0] - 1, IndexMap[connectIndex1][1], IndexMap[connectIndex1][2])] 130 | - VoxelTexture[id.xyz + uint3(IndexMap[connectIndex1][0] + 1, IndexMap[connectIndex1][1], IndexMap[connectIndex1][2])]; 131 | 132 | normal1.y = VoxelTexture[id.xyz + uint3(IndexMap[connectIndex1][0], IndexMap[connectIndex1][1] - 1, IndexMap[connectIndex1][2])] 133 | - VoxelTexture[id.xyz + uint3(IndexMap[connectIndex1][0], IndexMap[connectIndex1][1] + 1, IndexMap[connectIndex1][2])]; 134 | 135 | normal1.z = VoxelTexture[id.xyz + uint3(IndexMap[connectIndex1][0], IndexMap[connectIndex1][1], IndexMap[connectIndex1][2] - 1)] 136 | - VoxelTexture[id.xyz + uint3(IndexMap[connectIndex1][0], IndexMap[connectIndex1][1], IndexMap[connectIndex1][2] + 1)]; 137 | 138 | normal2.x = VoxelTexture[id.xyz + uint3(IndexMap[connectIndex2][0] - 1, IndexMap[connectIndex2][1], IndexMap[connectIndex2][2])] 139 | - VoxelTexture[id.xyz + uint3(IndexMap[connectIndex2][0] + 1, IndexMap[connectIndex2][1], IndexMap[connectIndex2][2])]; 140 | 141 | normal2.y = VoxelTexture[id.xyz + uint3(IndexMap[connectIndex2][0], IndexMap[connectIndex2][1] - 1, IndexMap[connectIndex2][2])] 142 | - VoxelTexture[id.xyz + uint3(IndexMap[connectIndex2][0], IndexMap[connectIndex2][1] + 1, IndexMap[connectIndex2][2])]; 143 | 144 | normal2.z = VoxelTexture[id.xyz + uint3(IndexMap[connectIndex2][0], IndexMap[connectIndex2][1], IndexMap[connectIndex2][2] - 1)] 145 | - VoxelTexture[id.xyz + uint3(IndexMap[connectIndex2][0], IndexMap[connectIndex2][1], IndexMap[connectIndex2][2] + 1)]; 146 | 147 | normal1 = normalize(normal1); 148 | normal2 = normalize(normal2); 149 | finalNormal = (1-lerpRatio) * normal1 + lerpRatio * normal2; 150 | 151 | 152 | if (k == 0) { 153 | tempTri.normalC = finalNormal; 154 | } 155 | else if (k == 1) { 156 | tempTri.normalB = finalNormal; 157 | } 158 | else if (k == 2) { 159 | tempTri.normalA = finalNormal; 160 | } 161 | } 162 | } 163 | 164 | if (!EnableSmooth) { 165 | float3 tempNormal = cross(tempTri.posB - tempTri.posA, tempTri.posC - tempTri.posA); 166 | tempTri.normalA = tempNormal; 167 | tempTri.normalB = tempNormal; 168 | tempTri.normalC = tempNormal; 169 | } 170 | Tribuffer.Append(tempTri); 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /[1]MarchingCube/MarchingCube.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 1 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 0} 41 | m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_EnvironmentLightingMode: 0 54 | m_EnableBakedLightmaps: 1 55 | m_EnableRealtimeLightmaps: 1 56 | m_LightmapEditorSettings: 57 | serializedVersion: 12 58 | m_Resolution: 2 59 | m_BakeResolution: 40 60 | m_AtlasSize: 1024 61 | m_AO: 0 62 | m_AOMaxDistance: 1 63 | m_CompAOExponent: 1 64 | m_CompAOExponentDirect: 0 65 | m_ExtractAmbientOcclusion: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 1 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 500 79 | m_PVRBounces: 2 80 | m_PVREnvironmentSampleCount: 500 81 | m_PVREnvironmentReferencePointCount: 2048 82 | m_PVRFilteringMode: 2 83 | m_PVRDenoiserTypeDirect: 0 84 | m_PVRDenoiserTypeIndirect: 0 85 | m_PVRDenoiserTypeAO: 0 86 | m_PVRFilterTypeDirect: 0 87 | m_PVRFilterTypeIndirect: 0 88 | m_PVRFilterTypeAO: 0 89 | m_PVREnvironmentMIS: 0 90 | m_PVRCulling: 1 91 | m_PVRFilteringGaussRadiusDirect: 1 92 | m_PVRFilteringGaussRadiusIndirect: 5 93 | m_PVRFilteringGaussRadiusAO: 2 94 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 95 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 96 | m_PVRFilteringAtrousPositionSigmaAO: 1 97 | m_ExportTrainingData: 0 98 | m_TrainingDataDestination: TrainingData 99 | m_LightingDataAsset: {fileID: 0} 100 | m_UseShadowmask: 1 101 | --- !u!196 &4 102 | NavMeshSettings: 103 | serializedVersion: 2 104 | m_ObjectHideFlags: 0 105 | m_BuildSettings: 106 | serializedVersion: 2 107 | agentTypeID: 0 108 | agentRadius: 0.5 109 | agentHeight: 2 110 | agentSlope: 45 111 | agentClimb: 0.4 112 | ledgeDropHeight: 0 113 | maxJumpAcrossDistance: 0 114 | minRegionArea: 2 115 | manualCellSize: 0 116 | cellSize: 0.16666667 117 | manualTileSize: 0 118 | tileSize: 256 119 | accuratePlacement: 0 120 | debug: 121 | m_Flags: 0 122 | m_NavMeshData: {fileID: 0} 123 | --- !u!1 &214601119 124 | GameObject: 125 | m_ObjectHideFlags: 0 126 | m_CorrespondingSourceObject: {fileID: 0} 127 | m_PrefabInstance: {fileID: 0} 128 | m_PrefabAsset: {fileID: 0} 129 | serializedVersion: 6 130 | m_Component: 131 | - component: {fileID: 214601121} 132 | - component: {fileID: 214601120} 133 | m_Layer: 0 134 | m_Name: Directional Light (1) 135 | m_TagString: Untagged 136 | m_Icon: {fileID: 0} 137 | m_NavMeshLayer: 0 138 | m_StaticEditorFlags: 0 139 | m_IsActive: 1 140 | --- !u!108 &214601120 141 | Light: 142 | m_ObjectHideFlags: 0 143 | m_CorrespondingSourceObject: {fileID: 0} 144 | m_PrefabInstance: {fileID: 0} 145 | m_PrefabAsset: {fileID: 0} 146 | m_GameObject: {fileID: 214601119} 147 | m_Enabled: 1 148 | serializedVersion: 9 149 | m_Type: 1 150 | m_Color: {r: 1, g: 1, b: 1, a: 1} 151 | m_Intensity: 4 152 | m_Range: 10 153 | m_SpotAngle: 30 154 | m_InnerSpotAngle: 21.80208 155 | m_CookieSize: 10 156 | m_Shadows: 157 | m_Type: 2 158 | m_Resolution: -1 159 | m_CustomResolution: -1 160 | m_Strength: 1 161 | m_Bias: 0.05 162 | m_NormalBias: 0.4 163 | m_NearPlane: 0.2 164 | m_CullingMatrixOverride: 165 | e00: 1 166 | e01: 0 167 | e02: 0 168 | e03: 0 169 | e10: 0 170 | e11: 1 171 | e12: 0 172 | e13: 0 173 | e20: 0 174 | e21: 0 175 | e22: 1 176 | e23: 0 177 | e30: 0 178 | e31: 0 179 | e32: 0 180 | e33: 1 181 | m_UseCullingMatrixOverride: 0 182 | m_Cookie: {fileID: 0} 183 | m_DrawHalo: 0 184 | m_Flare: {fileID: 0} 185 | m_RenderMode: 0 186 | m_CullingMask: 187 | serializedVersion: 2 188 | m_Bits: 4294967295 189 | m_RenderingLayerMask: 1 190 | m_Lightmapping: 4 191 | m_LightShadowCasterMode: 2 192 | m_AreaSize: {x: 1, y: 1} 193 | m_BounceIntensity: 1 194 | m_ColorTemperature: 6570 195 | m_UseColorTemperature: 0 196 | m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} 197 | m_UseBoundingSphereOverride: 0 198 | m_ShadowRadius: 0 199 | m_ShadowAngle: 0 200 | --- !u!4 &214601121 201 | Transform: 202 | m_ObjectHideFlags: 0 203 | m_CorrespondingSourceObject: {fileID: 0} 204 | m_PrefabInstance: {fileID: 0} 205 | m_PrefabAsset: {fileID: 0} 206 | m_GameObject: {fileID: 214601119} 207 | m_LocalRotation: {x: 0.32431263, y: 0.58110803, z: -0.2709751, w: 0.6954907} 208 | m_LocalPosition: {x: 0, y: 3, z: 0} 209 | m_LocalScale: {x: 1, y: 1, z: 1} 210 | m_Children: [] 211 | m_Father: {fileID: 0} 212 | m_RootOrder: 1 213 | m_LocalEulerAnglesHint: {x: 50, y: 79.76, z: 0} 214 | --- !u!1 &798155398 215 | GameObject: 216 | m_ObjectHideFlags: 0 217 | m_CorrespondingSourceObject: {fileID: 0} 218 | m_PrefabInstance: {fileID: 0} 219 | m_PrefabAsset: {fileID: 0} 220 | serializedVersion: 6 221 | m_Component: 222 | - component: {fileID: 798155399} 223 | - component: {fileID: 798155400} 224 | m_Layer: 0 225 | m_Name: MarchingCubeGpu 226 | m_TagString: Untagged 227 | m_Icon: {fileID: 0} 228 | m_NavMeshLayer: 0 229 | m_StaticEditorFlags: 0 230 | m_IsActive: 0 231 | --- !u!4 &798155399 232 | Transform: 233 | m_ObjectHideFlags: 0 234 | m_CorrespondingSourceObject: {fileID: 0} 235 | m_PrefabInstance: {fileID: 0} 236 | m_PrefabAsset: {fileID: 0} 237 | m_GameObject: {fileID: 798155398} 238 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 239 | m_LocalPosition: {x: 0, y: 0, z: 0} 240 | m_LocalScale: {x: 1, y: 1, z: 1} 241 | m_Children: [] 242 | m_Father: {fileID: 0} 243 | m_RootOrder: 3 244 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 245 | --- !u!114 &798155400 246 | MonoBehaviour: 247 | m_ObjectHideFlags: 0 248 | m_CorrespondingSourceObject: {fileID: 0} 249 | m_PrefabInstance: {fileID: 0} 250 | m_PrefabAsset: {fileID: 0} 251 | m_GameObject: {fileID: 798155398} 252 | m_Enabled: 1 253 | m_EditorHideFlags: 0 254 | m_Script: {fileID: 11500000, guid: ff2623e4a2eeb4bed96725ed5da0688b, type: 3} 255 | m_Name: 256 | m_EditorClassIdentifier: 257 | marchingCS: {fileID: 7200000, guid: 57f46d0d73ef941d3af317ea301241bb, type: 3} 258 | CenterPos: {x: 0, y: 0, z: 0} 259 | EnableSmooth: 1 260 | mat: {fileID: 2100000, guid: 31d46de5a502a2b49bdb76ed1f39b6cd, type: 2} 261 | GridRes: 80 262 | GridW: 2 263 | NoiseInterval: 0.02 264 | IsoLevel: 0.4 265 | --- !u!1 &1014543687 266 | GameObject: 267 | m_ObjectHideFlags: 0 268 | m_CorrespondingSourceObject: {fileID: 0} 269 | m_PrefabInstance: {fileID: 0} 270 | m_PrefabAsset: {fileID: 0} 271 | serializedVersion: 6 272 | m_Component: 273 | - component: {fileID: 1014543689} 274 | - component: {fileID: 1014543688} 275 | m_Layer: 0 276 | m_Name: MarchingCubeCpu 277 | m_TagString: Untagged 278 | m_Icon: {fileID: 0} 279 | m_NavMeshLayer: 0 280 | m_StaticEditorFlags: 0 281 | m_IsActive: 1 282 | --- !u!114 &1014543688 283 | MonoBehaviour: 284 | m_ObjectHideFlags: 0 285 | m_CorrespondingSourceObject: {fileID: 0} 286 | m_PrefabInstance: {fileID: 0} 287 | m_PrefabAsset: {fileID: 0} 288 | m_GameObject: {fileID: 1014543687} 289 | m_Enabled: 1 290 | m_EditorHideFlags: 0 291 | m_Script: {fileID: 11500000, guid: 6c2a4369b15d9b04ea268ba9c2ab45a2, type: 3} 292 | m_Name: 293 | m_EditorClassIdentifier: 294 | res: 25 295 | gridW: 2 296 | startMat: {fileID: 2100000, guid: 31d46de5a502a2b49bdb76ed1f39b6cd, type: 2} 297 | noiseInterval: 10 298 | checkRatio: 0.5 299 | noiseSpeed: 20 300 | objPos: {x: 0, y: 0, z: 0} 301 | scaleRatio: 1 302 | objRotateSpeed: 0.1 303 | enableSmoothNormal: 0 304 | --- !u!4 &1014543689 305 | Transform: 306 | m_ObjectHideFlags: 0 307 | m_CorrespondingSourceObject: {fileID: 0} 308 | m_PrefabInstance: {fileID: 0} 309 | m_PrefabAsset: {fileID: 0} 310 | m_GameObject: {fileID: 1014543687} 311 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 312 | m_LocalPosition: {x: 0, y: 0, z: 0} 313 | m_LocalScale: {x: 1, y: 1, z: 1} 314 | m_Children: [] 315 | m_Father: {fileID: 0} 316 | m_RootOrder: 2 317 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 318 | --- !u!1 &2099808832 319 | GameObject: 320 | m_ObjectHideFlags: 0 321 | m_CorrespondingSourceObject: {fileID: 0} 322 | m_PrefabInstance: {fileID: 0} 323 | m_PrefabAsset: {fileID: 0} 324 | serializedVersion: 6 325 | m_Component: 326 | - component: {fileID: 2099808835} 327 | - component: {fileID: 2099808834} 328 | - component: {fileID: 2099808833} 329 | - component: {fileID: 2099808836} 330 | - component: {fileID: 2099808837} 331 | m_Layer: 0 332 | m_Name: Main Camera 333 | m_TagString: MainCamera 334 | m_Icon: {fileID: 0} 335 | m_NavMeshLayer: 0 336 | m_StaticEditorFlags: 0 337 | m_IsActive: 1 338 | --- !u!81 &2099808833 339 | AudioListener: 340 | m_ObjectHideFlags: 0 341 | m_CorrespondingSourceObject: {fileID: 0} 342 | m_PrefabInstance: {fileID: 0} 343 | m_PrefabAsset: {fileID: 0} 344 | m_GameObject: {fileID: 2099808832} 345 | m_Enabled: 1 346 | --- !u!20 &2099808834 347 | Camera: 348 | m_ObjectHideFlags: 0 349 | m_CorrespondingSourceObject: {fileID: 0} 350 | m_PrefabInstance: {fileID: 0} 351 | m_PrefabAsset: {fileID: 0} 352 | m_GameObject: {fileID: 2099808832} 353 | m_Enabled: 1 354 | serializedVersion: 2 355 | m_ClearFlags: 2 356 | m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0.019607844} 357 | m_projectionMatrixMode: 1 358 | m_GateFitMode: 2 359 | m_FOVAxisMode: 0 360 | m_SensorSize: {x: 36, y: 24} 361 | m_LensShift: {x: 0, y: 0} 362 | m_FocalLength: 50 363 | m_NormalizedViewPortRect: 364 | serializedVersion: 2 365 | x: 0 366 | y: 0 367 | width: 1 368 | height: 1 369 | near clip plane: 0.01 370 | far clip plane: 1000 371 | field of view: 28 372 | orthographic: 0 373 | orthographic size: 5 374 | m_Depth: 0 375 | m_CullingMask: 376 | serializedVersion: 2 377 | m_Bits: 4294967295 378 | m_RenderingPath: 3 379 | m_TargetTexture: {fileID: 0} 380 | m_TargetDisplay: 0 381 | m_TargetEye: 3 382 | m_HDR: 0 383 | m_AllowMSAA: 0 384 | m_AllowDynamicResolution: 0 385 | m_ForceIntoRT: 0 386 | m_OcclusionCulling: 1 387 | m_StereoConvergence: 10 388 | m_StereoSeparation: 0.022 389 | --- !u!4 &2099808835 390 | Transform: 391 | m_ObjectHideFlags: 0 392 | m_CorrespondingSourceObject: {fileID: 0} 393 | m_PrefabInstance: {fileID: 0} 394 | m_PrefabAsset: {fileID: 0} 395 | m_GameObject: {fileID: 2099808832} 396 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 397 | m_LocalPosition: {x: 0, y: 0, z: -5} 398 | m_LocalScale: {x: 1, y: 1, z: 1} 399 | m_Children: [] 400 | m_Father: {fileID: 0} 401 | m_RootOrder: 0 402 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 403 | --- !u!114 &2099808836 404 | MonoBehaviour: 405 | m_ObjectHideFlags: 0 406 | m_CorrespondingSourceObject: {fileID: 0} 407 | m_PrefabInstance: {fileID: 0} 408 | m_PrefabAsset: {fileID: 0} 409 | m_GameObject: {fileID: 2099808832} 410 | m_Enabled: 1 411 | m_EditorHideFlags: 0 412 | m_Script: {fileID: 11500000, guid: 999178050ffa16247a2e59ca9a64c8ee, type: 3} 413 | m_Name: 414 | m_EditorClassIdentifier: 415 | --- !u!114 &2099808837 416 | MonoBehaviour: 417 | m_ObjectHideFlags: 0 418 | m_CorrespondingSourceObject: {fileID: 0} 419 | m_PrefabInstance: {fileID: 0} 420 | m_PrefabAsset: {fileID: 0} 421 | m_GameObject: {fileID: 2099808832} 422 | m_Enabled: 1 423 | m_EditorHideFlags: 0 424 | m_Script: {fileID: 11500000, guid: 855c24b21068ca6449a4680af0c5645e, type: 3} 425 | m_Name: 426 | m_EditorClassIdentifier: 427 | -------------------------------------------------------------------------------- /[1]MarchingCube/GPU/WenzyMarchTables.compute: -------------------------------------------------------------------------------- 1 | static const float EdgePointDir[12][3] = 2 | { 3 | // 自己根据参考图手动定位(基于 unity 空间坐标系) 4 | {0.0, -1.0, 1.0},{1.0, -1.0, 0.0},{0.0, -1.0, -1.0},{-1.0, -1.0, 0.0}, 5 | 6 | {0.0, 1.0, 1.0},{1.0, 1.0, 0.0},{0.0, 1.0, -1.0},{-1.0, 1.0, 0.0}, 7 | 8 | {-1.0, 0.0, 1.0},{1.0, 0.0, 1.0},{ 1.0, 0.0, -1.0},{-1.0, 0.0, -1.0} 9 | 10 | }; 11 | 12 | static const float VertexPointDir[8][3] = 13 | { 14 | // 主要计算顶点的偏移。(8个)自己根据参考图手动定位(基于 unity 空间坐标系) 15 | {-1.0, -1.0, 1.0},{1.0, -1.0, 1.0},{1.0, -1.0, -1.0},{-1.0, -1.0, -1.0}, 16 | 17 | {-1.0, 1.0, 1.0},{1.0, 1.0, 1.0},{1.0, 1.0, -1.0},{-1.0, 1.0, -1.0} 18 | }; 19 | 20 | 21 | // 会映射到顶点,用于计算插值。 22 | static const int ConnectionMap[12][2] = 23 | { 24 | {0,1}, {1,2}, {2,3}, {3,0}, 25 | {4,5}, {5,6}, {6,7}, {7,4}, 26 | {0,4}, {1,5}, {2,6}, {3,7} 27 | }; 28 | 29 | // 计算平滑 normal 会用到 30 | static const int IndexMap[8][3] = 31 | { 32 | { 0,0,1 },{ 1,0,1},{ 1,0,0},{ 0,0,0},{ 0,1,1},{ 1,1,1},{ 1,1,0},{ 0,1,0} 33 | }; 34 | 35 | 36 | 37 | static const int TriangleTable[256][16] = { 38 | {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 39 | { 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 40 | { 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 41 | { 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 42 | { 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 43 | { 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 44 | { 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 45 | { 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, 46 | { 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 47 | { 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 48 | { 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 49 | { 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, 50 | { 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 51 | { 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, 52 | { 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, 53 | { 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 54 | { 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 55 | { 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 56 | { 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 57 | { 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, 58 | { 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 59 | { 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1 }, 60 | { 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, 61 | { 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, 62 | { 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 63 | { 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, 64 | { 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, 65 | { 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1 }, 66 | { 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1 }, 67 | { 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1 }, 68 | { 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, 69 | { 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1 }, 70 | { 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 71 | { 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 72 | { 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 73 | { 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, 74 | { 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 75 | { 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, 76 | { 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, 77 | { 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1 }, 78 | { 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 79 | { 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1 }, 80 | { 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1 }, 81 | { 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1 }, 82 | { 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1 }, 83 | { 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1 }, 84 | { 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1 }, 85 | { 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1 }, 86 | { 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 87 | { 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, 88 | { 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, 89 | { 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 90 | { 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1 }, 91 | { 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1 }, 92 | { 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1 }, 93 | { 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1 }, 94 | { 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1 }, 95 | { 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, 96 | { 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1 }, 97 | { 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1 }, 98 | { 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1 }, 99 | { 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1 }, 100 | { 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1 }, 101 | { 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 102 | { 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 103 | { 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 104 | { 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 105 | { 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, 106 | { 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 107 | { 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1 }, 108 | { 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, 109 | { 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1 }, 110 | { 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 111 | { 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, 112 | { 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1 }, 113 | { 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1 }, 114 | { 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, 115 | { 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, 116 | { 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1 }, 117 | { 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1 }, 118 | { 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 119 | { 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1 }, 120 | { 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1 }, 121 | { 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1 }, 122 | { 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1 }, 123 | { 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1 }, 124 | { 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1 }, 125 | { 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1 }, 126 | { 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1 }, 127 | { 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1 }, 128 | { 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1 }, 129 | { 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1 }, 130 | { 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1 }, 131 | { 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1 }, 132 | { 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1 }, 133 | { 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1 }, 134 | { 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 135 | { 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1 }, 136 | { 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, 137 | { 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, 138 | { 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, 139 | { 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1 }, 140 | { 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 141 | { 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1 }, 142 | { 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1 }, 143 | { 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1 }, 144 | { 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1 }, 145 | { 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1 }, 146 | { 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1 }, 147 | { 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1 }, 148 | { 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1 }, 149 | { 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 150 | { 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, 151 | { 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1 }, 152 | { 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1 }, 153 | { 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1 }, 154 | { 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, 155 | { 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1 }, 156 | { 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1 }, 157 | { 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 158 | { 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1 }, 159 | { 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1 }, 160 | { 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1 }, 161 | { 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1 }, 162 | { 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1 }, 163 | { 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 164 | { 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1 }, 165 | { 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 166 | { 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 167 | { 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 168 | { 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 169 | { 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, 170 | { 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 171 | { 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, 172 | { 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1 }, 173 | { 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1 }, 174 | { 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 175 | { 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, 176 | { 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1 }, 177 | { 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1 }, 178 | { 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, 179 | { 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1 }, 180 | { 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1 }, 181 | { 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1 }, 182 | { 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 183 | { 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, 184 | { 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1 }, 185 | { 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1 }, 186 | { 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1 }, 187 | { 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1 }, 188 | { 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1 }, 189 | { 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1 }, 190 | { 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, 191 | { 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 192 | { 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1 }, 193 | { 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1 }, 194 | { 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1 }, 195 | { 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1 }, 196 | { 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1 }, 197 | { 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 198 | { 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 199 | { 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1 }, 200 | { 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, 201 | { 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1 }, 202 | { 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1 }, 203 | { 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1 }, 204 | { 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1 }, 205 | { 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1 }, 206 | { 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1 }, 207 | { 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1 }, 208 | { 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1 }, 209 | { 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1 }, 210 | { 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1 }, 211 | { 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1 }, 212 | { 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1 }, 213 | { 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1 }, 214 | { 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, 215 | { 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1 }, 216 | { 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1 }, 217 | { 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1 }, 218 | { 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1 }, 219 | { 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1 }, 220 | { 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1 }, 221 | { 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1 }, 222 | { 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1 }, 223 | { 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1 }, 224 | { 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1 }, 225 | { 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 226 | { 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1 }, 227 | { 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1 }, 228 | { 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 229 | { 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 230 | { 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 231 | { 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1 }, 232 | { 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1 }, 233 | { 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1 }, 234 | { 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, 235 | { 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1 }, 236 | { 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1 }, 237 | { 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1 }, 238 | { 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, 239 | { 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1 }, 240 | { 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1 }, 241 | { 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1 }, 242 | { 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 243 | { 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1 }, 244 | { 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1 }, 245 | { 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 246 | { 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, 247 | { 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1 }, 248 | { 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1 }, 249 | { 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1 }, 250 | { 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1 }, 251 | { 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1 }, 252 | { 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1 }, 253 | { 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 254 | { 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1 }, 255 | { 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1 }, 256 | { 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1 }, 257 | { 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1 }, 258 | { 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1 }, 259 | { 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 260 | { 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1 }, 261 | { 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 262 | { 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, 263 | { 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1 }, 264 | { 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1 }, 265 | { 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1 }, 266 | { 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1 }, 267 | { 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1 }, 268 | { 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1 }, 269 | { 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1 }, 270 | { 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1 }, 271 | { 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1 }, 272 | { 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1 }, 273 | { 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 274 | { 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1 }, 275 | { 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1 }, 276 | { 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 277 | { 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 278 | { 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 279 | { 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1 }, 280 | { 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1 }, 281 | { 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 282 | { 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1 }, 283 | { 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1 }, 284 | { 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 285 | { 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 286 | { 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1 }, 287 | { 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 288 | { 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1 }, 289 | { 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 290 | { 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 291 | { 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 292 | { 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, 293 | {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } 294 | }; 295 | 296 | static const int cornerIndexAFromEdge[12] = { 297 | 0, 298 | 1, 299 | 2, 300 | 3, 301 | 4, 302 | 5, 303 | 6, 304 | 7, 305 | 0, 306 | 1, 307 | 2, 308 | 3 309 | }; 310 | 311 | static const int cornerIndexBFromEdge[12] = { 312 | 1, 313 | 2, 314 | 3, 315 | 0, 316 | 5, 317 | 6, 318 | 7, 319 | 4, 320 | 4, 321 | 5, 322 | 6, 323 | 7 324 | }; -------------------------------------------------------------------------------- /[1]MarchingCube/CPU/WenzyMarchingCubeCPU.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | 6 | public class WenzyMarchingCubeCPU : MonoBehaviour 7 | { 8 | public int res = 10; // grid resolution 9 | float[,,] val; // data val 的数量要比实际的 res 多 1 10 | public float gridW = 2f; 11 | float gridInterval; 12 | 13 | GameObject meshObj; 14 | public Material startMat; 15 | 16 | Mesh mesh; 17 | public float noiseInterval = 0.05f; 18 | [Range(0.001f,1)] 19 | public float checkRatio = 0.5f; 20 | public float noiseSpeed = 20f; 21 | public Vector3 objPos; 22 | public float scaleRatio = 1; 23 | public float objRotateSpeed = 0.1f; 24 | public bool enableSmoothNormal; 25 | 26 | void Start() 27 | { 28 | meshObj = new GameObject(); 29 | meshObj.AddComponent(); 30 | meshObj.AddComponent(); 31 | meshObj.GetComponent().material = startMat; 32 | 33 | mesh = meshObj.GetComponent().mesh; 34 | val = new float[res + 1, res + 1, res + 1]; 35 | } 36 | 37 | void UpdateData() 38 | { 39 | FastNoise fastNoise; 40 | fastNoise = new FastNoise(); 41 | 42 | float time = Time.time * noiseSpeed; 43 | for (int i = 0; i < res + 1; i++) 44 | { 45 | for (int j = 0; j < res + 1; j++) 46 | { 47 | for (int k = 0; k < res + 1; k++) 48 | { 49 | // fastNoise 's range from - 1 to 1 50 | val[i, j, k] = (fastNoise.GetSimplex(i * noiseInterval, j * noiseInterval, k * noiseInterval,time) + 1.0f)/2; 51 | // dual with boundray 52 | if (i == 0 || j == 0 || k == 0 || i == res || j == res || k == res) 53 | val[i, j, k] = 0; 54 | } 55 | } 56 | } 57 | } 58 | 59 | void UpdateMesh() 60 | { 61 | gridInterval = gridW / (float)res; 62 | 63 | List meshPos = new List(); 64 | List normalList = new List(); 65 | 66 | 67 | float[] valCollection = new float[8]; 68 | Vector3 centerOffset = new Vector3(); 69 | Vector3 dirOffset = new Vector3(); 70 | Vector3 p1 = new Vector3(); 71 | Vector3 p2 = new Vector3(); 72 | int connectIndex1, connectIndex2; 73 | Vector3 finalPos = new Vector3(); 74 | 75 | int index = 0; 76 | Vector3 normal1, normal2; 77 | float lerpRatio = 0; // 点的插值比例 78 | Vector3 tempNormal = new Vector3(); 79 | for (int i = 0; i < res; i++) 80 | { 81 | for (int j = 0; j < res; j++) 82 | { 83 | for (int k = 0; k < res; k++) 84 | { 85 | // 先添加的 0 需要推算出来 (注意这里添加的是 8 个顶点的亮灭 ) 86 | valCollection[0] = val[i, j, k + 1]; 87 | valCollection[1] = val[i + 1, j, k + 1]; 88 | valCollection[2] = val[i + 1, j, k]; 89 | valCollection[3] = val[i, j, k]; // 这个应该对应例图中的 3,如果基于 unity 坐标系去排列 90 | valCollection[4] = val[i, j + 1, k + 1]; // 4 91 | valCollection[5] = val[i + 1, j + 1, k + 1]; // 5 92 | valCollection[6] = val[i + 1, j + 1, k]; // 6 93 | valCollection[7] = val[i, j + 1, k]; // 7 94 | 95 | index = 0; 96 | for (int l = 0; l < 8; l++) 97 | { 98 | if (valCollection[l] >= checkRatio) 99 | index |= 1 << l; 100 | } 101 | 102 | // 目的是居中,需要注意: offset 的中点并不完全是 res * gridInterval, 需要两端再 - 半个 gridInterval 103 | centerOffset.x = (i / (res - 1.0f) - 0.5f) * (res - 1) * gridInterval; 104 | centerOffset.y = (j / (res - 1.0f) - 0.5f) * (res - 1) * gridInterval; 105 | centerOffset.z = (k / (res - 1.0f) - 0.5f) * (res - 1) * gridInterval; 106 | for (int l = 0; l < 16; l++) 107 | { 108 | if (TriangleTable[index, l] >= 0) 109 | { 110 | dirOffset.x = EdgePointDir[TriangleTable[index, l], 0]; 111 | dirOffset.y = EdgePointDir[TriangleTable[index, l], 1]; 112 | dirOffset.z = EdgePointDir[TriangleTable[index, l], 2]; 113 | 114 | connectIndex1 = ConnectionMap[TriangleTable[index, l], 0]; 115 | connectIndex2 = ConnectionMap[TriangleTable[index, l], 1]; 116 | 117 | p1.x = VertexPointDir[connectIndex1, 0]; 118 | p1.y = VertexPointDir[connectIndex1, 1]; 119 | p1.z = VertexPointDir[connectIndex1, 2]; 120 | 121 | p2.x = VertexPointDir[connectIndex2, 0]; 122 | p2.y = VertexPointDir[connectIndex2, 1]; 123 | p2.z = VertexPointDir[connectIndex2, 2]; 124 | 125 | p1 *= gridInterval; 126 | p2 *= gridInterval; 127 | p1 /= 2.0f; 128 | p2 /= 2.0f; 129 | // 根据论文的公式计算插值 130 | finalPos = p1 + (checkRatio - valCollection[connectIndex1]) * (p2 - p1) / (valCollection[connectIndex2] - valCollection[connectIndex1]); 131 | lerpRatio = Vector3.Distance(p1, finalPos) / Vector3.Distance(p1, p2); 132 | 133 | finalPos += centerOffset; 134 | meshPos.Add(finalPos ); 135 | 136 | // 手动对 normal 进行平滑化处理 137 | if (enableSmoothNormal) 138 | { // 先简化处理 139 | if (i != 0 && j != 0 && k != 0 && i < res - 1 && j < res - 1 && k < res - 1) 140 | { 141 | normal1.x = val[i + IndexMap[connectIndex1, 0] - 1, 142 | j + IndexMap[connectIndex1, 1], 143 | k + IndexMap[connectIndex1, 2]] 144 | - val[i + IndexMap[connectIndex1, 0] + 1, 145 | j + IndexMap[connectIndex1, 1], 146 | k + IndexMap[connectIndex1, 2]]; 147 | normal1.y = val[i + IndexMap[connectIndex1, 0], 148 | j + IndexMap[connectIndex1, 1] - 1, 149 | k + IndexMap[connectIndex1, 2]] 150 | - val[i + IndexMap[connectIndex1, 0], 151 | j + IndexMap[connectIndex1, 1] + 1, 152 | k + IndexMap[connectIndex1, 2]]; 153 | normal1.z = val[i + IndexMap[connectIndex1, 0], 154 | j + IndexMap[connectIndex1, 1], 155 | k + IndexMap[connectIndex1, 2] - 1] 156 | - val[i + IndexMap[connectIndex1, 0], 157 | j + IndexMap[connectIndex1, 1], 158 | k + IndexMap[connectIndex1, 2] + 1]; 159 | 160 | normal2.x = val[i + IndexMap[connectIndex2, 0] - 1, 161 | j + IndexMap[connectIndex2, 1], 162 | k + IndexMap[connectIndex2, 2]] 163 | - val[i + IndexMap[connectIndex2, 0] + 1, 164 | j + IndexMap[connectIndex2, 1], 165 | k + IndexMap[connectIndex2, 2]]; 166 | normal2.y = val[i + IndexMap[connectIndex2, 0], 167 | j + IndexMap[connectIndex2, 1] - 1, 168 | k + IndexMap[connectIndex2, 2]] 169 | - val[i + IndexMap[connectIndex2, 0], 170 | j + IndexMap[connectIndex2, 1] + 1, 171 | k + IndexMap[connectIndex2, 2]]; 172 | normal2.z = val[i + IndexMap[connectIndex2, 0], 173 | j + IndexMap[connectIndex2, 1], 174 | k + IndexMap[connectIndex2, 2] - 1] 175 | - val[i + IndexMap[connectIndex2, 0], 176 | j + IndexMap[connectIndex2, 1], 177 | k + IndexMap[connectIndex2, 2] + 1]; 178 | 179 | normal1.Normalize(); 180 | normal2.Normalize(); 181 | } 182 | else 183 | { 184 | normal1 = new Vector3(); 185 | normal2 = new Vector3(); 186 | } 187 | tempNormal =(1 - lerpRatio) * normal1 + lerpRatio * normal2; 188 | normalList.Add(tempNormal); 189 | } 190 | } 191 | else 192 | { 193 | break; 194 | } 195 | } 196 | } 197 | } 198 | } 199 | 200 | mesh.Clear(); 201 | mesh.SetVertices(meshPos); 202 | 203 | List triList = new List(); 204 | 205 | for(int i = 0;i < meshPos.Count;i++) 206 | { 207 | triList.Add(meshPos.Count - 1 - i); 208 | } 209 | mesh.SetTriangles(triList, 0); 210 | 211 | if (enableSmoothNormal) 212 | { 213 | mesh.SetNormals(normalList); 214 | } 215 | else 216 | { 217 | mesh.RecalculateNormals(); 218 | } 219 | } 220 | 221 | protected float GetOffset(float v1, float v2) 222 | { 223 | float delta = v2 - v1; 224 | return (delta == 0.0f) ? checkRatio : (checkRatio - v1) / delta; 225 | } 226 | 227 | Vector3 VertexInterp(Vector3 p1, Vector3 p2, float valp1, float valp2) 228 | 229 | { 230 | float mu; 231 | Vector3 p; 232 | 233 | if (Mathf.Abs(checkRatio - valp1) < 0.00001) 234 | return (p1); 235 | if (Mathf.Abs(checkRatio - valp2) < 0.00001) 236 | return (p2); 237 | if (Mathf.Abs(valp1 - valp2) < 0.00001) 238 | return (p1); 239 | mu = (checkRatio - valp1) / (valp2 - valp1); 240 | p.x = p1.x + mu * (p2.x - p1.x); 241 | p.y = p1.y + mu * (p2.y - p1.y); 242 | p.z = p1.z + mu * (p2.z - p1.z); 243 | 244 | return (p); 245 | } 246 | 247 | 248 | void Update() 249 | { 250 | UpdateData(); 251 | UpdateMesh(); 252 | meshObj.transform.position = objPos; 253 | //meshObj.transform.Rotate(new Vector3(0, 1, 0), objRotateSpeed); 254 | } 255 | 256 | // 参考脚本: C# 数据版 257 | // https://github.com/Scrawk/Marching-Cubes/blob/master/Assets/MarchingCubes/Marching/MarchingCubes.cs 258 | 259 | 260 | private static readonly float[,] EdgePointDir = new float[,] 261 | { 262 | // 自己根据参考图手动定位(基于 unity 空间坐标系) 263 | {0.0f, -1.0f, 1.0f},{1.0f, -1.0f, 0.0f},{0.0f, -1.0f, -1.0f},{-1.0f, -1.0f, 0.0f}, 264 | 265 | {0.0f, 1.0f, 1.0f},{1.0f, 1.0f, 0.0f},{0.0f, 1.0f, -1.0f},{-1.0f, 1.0f, 0.0f}, 266 | 267 | {-1.0f, 0.0f, 1.0f},{1.0f, 0.0f, 1.0f},{ 1.0f, 0.0f, -1.0f},{-1.0f, 0.0f, -1.0f} 268 | 269 | }; 270 | 271 | // 会映射到顶点,用于计算插值。 272 | private static readonly int[,] ConnectionMap = new int[,] 273 | { 274 | {0,1}, {1,2}, {2,3}, {3,0}, 275 | {4,5}, {5,6}, {6,7}, {7,4}, 276 | {0,4}, {1,5}, {2,6}, {3,7} 277 | }; 278 | 279 | 280 | 281 | // 计算平滑 normal 会用到, 这个应该对应例图中的 3,如果基于 unity 坐标系去排列 282 | private static readonly int[,] IndexMap = new int[,] 283 | { 284 | { 0,0,1 },{ 1,0,1},{ 1,0,0},{ 0,0,0},{ 0,1,1},{ 1,1,1},{ 1,1,0},{ 0,1,0} 285 | }; 286 | 287 | 288 | 289 | private static readonly float[,] VertexPointDir = new float[,] 290 | { 291 | // 主要计算顶点的偏移。(8个)自己根据参考图手动定位(基于 unity 空间坐标系) 292 | {-1.0f, -1.0f, 1.0f},{1.0f, -1.0f, 1.0f},{1.0f, -1.0f, -1.0f},{-1.0f, -1.0f, -1.0f}, 293 | 294 | {-1.0f, 1.0f, 1.0f},{1.0f, 1.0f, 1.0f},{1.0f, 1.0f, -1.0f},{-1.0f, 1.0f, -1.0f} 295 | }; 296 | // 16 * 16 297 | private static readonly int[] CubeEdgeFlags = new int[] 298 | 299 | { 300 | 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 301 | 302 | 0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 303 | 304 | 0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 305 | 306 | 0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 307 | 308 | 0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 309 | 310 | 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 311 | 312 | 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 313 | 314 | 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 315 | 316 | 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 317 | 318 | 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 319 | 320 | 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 321 | 322 | 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460, 323 | 324 | 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0, 325 | 326 | 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230, 327 | 328 | 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190, 329 | 330 | 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000 331 | 332 | }; 333 | 334 | // 如果输出二维数组的 length ,会是 256 * 16 = 4096 335 | private static readonly int[,] TriangleTable = new int[,] 336 | 337 | { 338 | 339 | {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 340 | 341 | {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 342 | 343 | {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 344 | 345 | {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 346 | 347 | {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 348 | 349 | {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 350 | 351 | {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 352 | 353 | {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1}, 354 | 355 | {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 356 | 357 | {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 358 | 359 | {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 360 | 361 | {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1}, 362 | 363 | {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 364 | 365 | {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1}, 366 | 367 | {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, 368 | 369 | {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 370 | 371 | {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 372 | 373 | {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 374 | 375 | {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 376 | 377 | {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1}, 378 | 379 | {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 380 | 381 | {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1}, 382 | 383 | {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, 384 | 385 | {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1}, 386 | 387 | {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 388 | 389 | {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1}, 390 | 391 | {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, 392 | 393 | {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1}, 394 | 395 | {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, 396 | 397 | {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1}, 398 | 399 | {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1}, 400 | 401 | {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1}, 402 | 403 | {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 404 | 405 | {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 406 | 407 | {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 408 | 409 | {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1}, 410 | 411 | {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 412 | 413 | {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, 414 | 415 | {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, 416 | 417 | {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1}, 418 | 419 | {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 420 | 421 | {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1}, 422 | 423 | {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, 424 | 425 | {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1}, 426 | 427 | {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, 428 | 429 | {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1}, 430 | 431 | {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1}, 432 | 433 | {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1}, 434 | 435 | {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 436 | 437 | {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1}, 438 | 439 | {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, 440 | 441 | {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 442 | 443 | {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1}, 444 | 445 | {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1}, 446 | 447 | {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1}, 448 | 449 | {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1}, 450 | 451 | {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1}, 452 | 453 | {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1}, 454 | 455 | {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1}, 456 | 457 | {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1}, 458 | 459 | {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1}, 460 | 461 | {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1}, 462 | 463 | {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1}, 464 | 465 | {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 466 | 467 | {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 468 | 469 | {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 470 | 471 | {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 472 | 473 | {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, 474 | 475 | {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 476 | 477 | {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1}, 478 | 479 | {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, 480 | 481 | {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1}, 482 | 483 | {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 484 | 485 | {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, 486 | 487 | {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, 488 | 489 | {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1}, 490 | 491 | {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, 492 | 493 | {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1}, 494 | 495 | {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, 496 | 497 | {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1}, 498 | 499 | {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 500 | 501 | {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1}, 502 | 503 | {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, 504 | 505 | {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1}, 506 | 507 | {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, 508 | 509 | {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1}, 510 | 511 | {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1}, 512 | 513 | {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1}, 514 | 515 | {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, 516 | 517 | {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1}, 518 | 519 | {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}, 520 | 521 | {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1}, 522 | 523 | {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1}, 524 | 525 | {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1}, 526 | 527 | {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1}, 528 | 529 | {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1}, 530 | 531 | {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 532 | 533 | {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1}, 534 | 535 | {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, 536 | 537 | {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1}, 538 | 539 | {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, 540 | 541 | {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1}, 542 | 543 | {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 544 | 545 | {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1}, 546 | 547 | {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1}, 548 | 549 | {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1}, 550 | 551 | {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1}, 552 | 553 | {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1}, 554 | 555 | {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1}, 556 | 557 | {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1}, 558 | 559 | {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, 560 | 561 | {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 562 | 563 | {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, 564 | 565 | {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1}, 566 | 567 | {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, 568 | 569 | {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1}, 570 | 571 | {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, 572 | 573 | {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1}, 574 | 575 | {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, 576 | 577 | {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 578 | 579 | {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1}, 580 | 581 | {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1}, 582 | 583 | {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1}, 584 | 585 | {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1}, 586 | 587 | {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1}, 588 | 589 | {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 590 | 591 | {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1}, 592 | 593 | {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 594 | 595 | {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 596 | 597 | {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 598 | 599 | {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 600 | 601 | {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, 602 | 603 | {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 604 | 605 | {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, 606 | 607 | {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, 608 | 609 | {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1}, 610 | 611 | {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 612 | 613 | {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1}, 614 | 615 | {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, 616 | 617 | {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1}, 618 | 619 | {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, 620 | 621 | {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1}, 622 | 623 | {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1}, 624 | 625 | {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1}, 626 | 627 | {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 628 | 629 | {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1}, 630 | 631 | {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, 632 | 633 | {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1}, 634 | 635 | {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}, 636 | 637 | {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1}, 638 | 639 | {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1}, 640 | 641 | {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1}, 642 | 643 | {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, 644 | 645 | {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 646 | 647 | {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1}, 648 | 649 | {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1}, 650 | 651 | {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1}, 652 | 653 | {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1}, 654 | 655 | {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1}, 656 | 657 | {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 658 | 659 | {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 660 | 661 | {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1}, 662 | 663 | {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, 664 | 665 | {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1}, 666 | 667 | {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, 668 | 669 | {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1}, 670 | 671 | {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1}, 672 | 673 | {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1}, 674 | 675 | {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, 676 | 677 | {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1}, 678 | 679 | {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1}, 680 | 681 | {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1}, 682 | 683 | {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1}, 684 | 685 | {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1}, 686 | 687 | {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1}, 688 | 689 | {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1}, 690 | 691 | {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, 692 | 693 | {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1}, 694 | 695 | {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1}, 696 | 697 | {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1}, 698 | 699 | {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1}, 700 | 701 | {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1}, 702 | 703 | {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1}, 704 | 705 | {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1}, 706 | 707 | {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, 708 | 709 | {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1}, 710 | 711 | {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1}, 712 | 713 | {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 714 | 715 | {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1}, 716 | 717 | {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1}, 718 | 719 | {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 720 | 721 | {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 722 | 723 | {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 724 | 725 | {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1}, 726 | 727 | {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, 728 | 729 | {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1}, 730 | 731 | {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, 732 | 733 | {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1}, 734 | 735 | {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1}, 736 | 737 | {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1}, 738 | 739 | {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, 740 | 741 | {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1}, 742 | 743 | {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1}, 744 | 745 | {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1}, 746 | 747 | {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 748 | 749 | {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1}, 750 | 751 | {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, 752 | 753 | {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 754 | 755 | {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, 756 | 757 | {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1}, 758 | 759 | {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1}, 760 | 761 | {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1}, 762 | 763 | {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1}, 764 | 765 | {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1}, 766 | 767 | {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1}, 768 | 769 | {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 770 | 771 | {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, 772 | 773 | {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1}, 774 | 775 | {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1}, 776 | 777 | {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1}, 778 | 779 | {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, 780 | 781 | {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 782 | 783 | {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1}, 784 | 785 | {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 786 | 787 | {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, 788 | 789 | {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1}, 790 | 791 | {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1}, 792 | 793 | {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1}, 794 | 795 | {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1}, 796 | 797 | {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1}, 798 | 799 | {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, 800 | 801 | {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1}, 802 | 803 | {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, 804 | 805 | {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1}, 806 | 807 | {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1}, 808 | 809 | {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 810 | 811 | {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, 812 | 813 | {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1}, 814 | 815 | {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 816 | 817 | {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 818 | 819 | {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 820 | 821 | {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1}, 822 | 823 | {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, 824 | 825 | {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 826 | 827 | {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, 828 | 829 | {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1}, 830 | 831 | {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 832 | 833 | {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 834 | 835 | {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, 836 | 837 | {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 838 | 839 | {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1}, 840 | 841 | {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 842 | 843 | {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 844 | 845 | {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 846 | 847 | {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 848 | 849 | {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} 850 | 851 | }; 852 | 853 | 854 | } 855 | -------------------------------------------------------------------------------- /[1]MarchingCube/CPU/FastNoise.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | // FastNoise.cs 4 | // 5 | // MIT License 6 | // 7 | // Copyright(c) 2017 Jordan Peck 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files(the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions : 15 | // 16 | // The above copyright notice and this permission notice shall be included in all 17 | // copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | // SOFTWARE. 26 | // 27 | // The developer's email is jorzixdan.me2@gzixmail.com (for great email, take 28 | // off every 'zix'.) 29 | // 30 | 31 | // Uncomment the line below to swap all the inputs/outputs/calculations of FastNoise to doubles instead of floats 32 | //#define FN_USE_DOUBLES 33 | 34 | #if FN_USE_DOUBLES 35 | using FN_DECIMAL = System.Double; 36 | #else 37 | using FN_DECIMAL = System.Single; 38 | #endif 39 | 40 | using System; 41 | using System.Runtime.CompilerServices; 42 | 43 | public class FastNoise 44 | { 45 | private const Int16 FN_INLINE = 256; //(Int16)MethodImplOptions.AggressiveInlining; 46 | private const int FN_CELLULAR_INDEX_MAX = 3; 47 | 48 | public enum NoiseType { Value, ValueFractal, Perlin, PerlinFractal, Simplex, SimplexFractal, Cellular, WhiteNoise, Cubic, CubicFractal }; 49 | public enum Interp { Linear, Hermite, Quintic }; 50 | public enum FractalType { FBM, Billow, RigidMulti }; 51 | public enum CellularDistanceFunction { Euclidean, Manhattan, Natural }; 52 | public enum CellularReturnType { CellValue, NoiseLookup, Distance, Distance2, Distance2Add, Distance2Sub, Distance2Mul, Distance2Div }; 53 | 54 | private int m_seed = 1337; 55 | private FN_DECIMAL m_frequency = (FN_DECIMAL)0.01; 56 | private Interp m_interp = Interp.Quintic; 57 | private NoiseType m_noiseType = NoiseType.Simplex; 58 | 59 | private int m_octaves = 3; 60 | private FN_DECIMAL m_lacunarity = (FN_DECIMAL)2.0; 61 | private FN_DECIMAL m_gain = (FN_DECIMAL)0.5; 62 | private FractalType m_fractalType = FractalType.FBM; 63 | 64 | private FN_DECIMAL m_fractalBounding; 65 | 66 | private CellularDistanceFunction m_cellularDistanceFunction = CellularDistanceFunction.Euclidean; 67 | private CellularReturnType m_cellularReturnType = CellularReturnType.CellValue; 68 | private FastNoise m_cellularNoiseLookup = null; 69 | private int m_cellularDistanceIndex0 = 0; 70 | private int m_cellularDistanceIndex1 = 1; 71 | private float m_cellularJitter = 0.45f; 72 | 73 | private FN_DECIMAL m_gradientPerturbAmp = (FN_DECIMAL)1.0; 74 | 75 | public FastNoise(int seed = 1337) 76 | { 77 | m_seed = seed; 78 | CalculateFractalBounding(); 79 | } 80 | 81 | // Returns a 0 float/double 82 | public static FN_DECIMAL GetDecimalType() { return 0; } 83 | 84 | // Returns the seed used by this object 85 | public int GetSeed() { return m_seed; } 86 | 87 | // Sets seed used for all noise types 88 | // Default: 1337 89 | public void SetSeed(int seed) { m_seed = seed; } 90 | 91 | // Sets frequency for all noise types 92 | // Default: 0.01 93 | public void SetFrequency(FN_DECIMAL frequency) { m_frequency = frequency; } 94 | 95 | // Changes the interpolation method used to smooth between noise values 96 | // Possible interpolation methods (lowest to highest quality) : 97 | // - Linear 98 | // - Hermite 99 | // - Quintic 100 | // Used in Value, Gradient Noise and Position Perturbing 101 | // Default: Quintic 102 | public void SetInterp(Interp interp) { m_interp = interp; } 103 | 104 | // Sets noise return type of GetNoise(...) 105 | // Default: Simplex 106 | public void SetNoiseType(NoiseType noiseType) { m_noiseType = noiseType; } 107 | 108 | 109 | // Sets octave count for all fractal noise types 110 | // Default: 3 111 | public void SetFractalOctaves(int octaves) { m_octaves = octaves; CalculateFractalBounding(); } 112 | 113 | // Sets octave lacunarity for all fractal noise types 114 | // Default: 2.0 115 | public void SetFractalLacunarity(FN_DECIMAL lacunarity) { m_lacunarity = lacunarity; } 116 | 117 | // Sets octave gain for all fractal noise types 118 | // Default: 0.5 119 | public void SetFractalGain(FN_DECIMAL gain) { m_gain = gain; CalculateFractalBounding(); } 120 | 121 | // Sets method for combining octaves in all fractal noise types 122 | // Default: FBM 123 | public void SetFractalType(FractalType fractalType) { m_fractalType = fractalType; } 124 | 125 | 126 | // Sets return type from cellular noise calculations 127 | // Note: NoiseLookup requires another FastNoise object be set with SetCellularNoiseLookup() to function 128 | // Default: CellValue 129 | public void SetCellularDistanceFunction(CellularDistanceFunction cellularDistanceFunction) { m_cellularDistanceFunction = cellularDistanceFunction; } 130 | 131 | // Sets distance function used in cellular noise calculations 132 | // Default: Euclidean 133 | public void SetCellularReturnType(CellularReturnType cellularReturnType) { m_cellularReturnType = cellularReturnType; } 134 | 135 | // Sets the 2 distance indicies used for distance2 return types 136 | // Default: 0, 1 137 | // Note: index0 should be lower than index1 138 | // Both indicies must be >= 0, index1 must be < 4 139 | public void SetCellularDistance2Indicies(int cellularDistanceIndex0, int cellularDistanceIndex1) 140 | { 141 | m_cellularDistanceIndex0 = Math.Min(cellularDistanceIndex0, cellularDistanceIndex1); 142 | m_cellularDistanceIndex1 = Math.Max(cellularDistanceIndex0, cellularDistanceIndex1); 143 | 144 | m_cellularDistanceIndex0 = Math.Min(Math.Max(m_cellularDistanceIndex0, 0), FN_CELLULAR_INDEX_MAX); 145 | m_cellularDistanceIndex1 = Math.Min(Math.Max(m_cellularDistanceIndex1, 0), FN_CELLULAR_INDEX_MAX); 146 | } 147 | 148 | // Sets the maximum distance a cellular point can move from it's grid position 149 | // Setting this high will make artifacts more common 150 | // Default: 0.45 151 | public void SetCellularJitter(float cellularJitter) { m_cellularJitter = cellularJitter; } 152 | 153 | // Noise used to calculate a cell value if cellular return type is NoiseLookup 154 | // The lookup value is acquired through GetNoise() so ensure you SetNoiseType() on the noise lookup, value, gradient or simplex is recommended 155 | public void SetCellularNoiseLookup(FastNoise noise) { m_cellularNoiseLookup = noise; } 156 | 157 | 158 | // Sets the maximum perturb distance from original location when using GradientPerturb{Fractal}(...) 159 | // Default: 1.0 160 | public void SetGradientPerturbAmp(FN_DECIMAL gradientPerturbAmp) { m_gradientPerturbAmp = gradientPerturbAmp; } 161 | 162 | private struct Float2 163 | { 164 | public readonly FN_DECIMAL x, y; 165 | public Float2(FN_DECIMAL x, FN_DECIMAL y) 166 | { 167 | this.x = x; 168 | this.y = y; 169 | } 170 | } 171 | 172 | private struct Float3 173 | { 174 | public readonly FN_DECIMAL x, y, z; 175 | public Float3(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 176 | { 177 | this.x = x; 178 | this.y = y; 179 | this.z = z; 180 | } 181 | } 182 | 183 | private static readonly Float2[] GRAD_2D = { 184 | new Float2(-1,-1), new Float2( 1,-1), new Float2(-1, 1), new Float2( 1, 1), 185 | new Float2( 0,-1), new Float2(-1, 0), new Float2( 0, 1), new Float2( 1, 0), 186 | }; 187 | 188 | private static readonly Float3[] GRAD_3D = { 189 | new Float3( 1, 1, 0), new Float3(-1, 1, 0), new Float3( 1,-1, 0), new Float3(-1,-1, 0), 190 | new Float3( 1, 0, 1), new Float3(-1, 0, 1), new Float3( 1, 0,-1), new Float3(-1, 0,-1), 191 | new Float3( 0, 1, 1), new Float3( 0,-1, 1), new Float3( 0, 1,-1), new Float3( 0,-1,-1), 192 | new Float3( 1, 1, 0), new Float3( 0,-1, 1), new Float3(-1, 1, 0), new Float3( 0,-1,-1), 193 | }; 194 | 195 | private static readonly Float2[] CELL_2D = 196 | { 197 | 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), 198 | 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), 199 | 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), 200 | 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), 201 | 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), 202 | 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), 203 | 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), 204 | 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), 205 | 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), 206 | 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), 207 | 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), 208 | 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), 209 | 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), 210 | 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), 211 | 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), 212 | 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), 213 | 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), 214 | 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), 215 | 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), 216 | 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), 217 | 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), 218 | 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), 219 | 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), 220 | 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), 221 | 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), 222 | 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), 223 | 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), 224 | 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), 225 | 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), 226 | 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), 227 | 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), 228 | 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), 229 | }; 230 | 231 | private static readonly Float3[] CELL_3D = 232 | { 233 | 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), 234 | 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), 235 | 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), 236 | 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), 237 | 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), 238 | 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), 239 | 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), 240 | 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), 241 | 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), 242 | 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), 243 | 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), 244 | 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), 245 | 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), 246 | 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), 247 | 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), 248 | 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), 249 | 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), 250 | 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), 251 | 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), 252 | 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), 253 | 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), 254 | 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), 255 | 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), 256 | 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), 257 | 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), 258 | 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), 259 | 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), 260 | 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), 261 | 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), 262 | 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), 263 | 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), 264 | 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), 265 | }; 266 | 267 | [MethodImplAttribute(FN_INLINE)] 268 | private static int FastFloor(FN_DECIMAL f) { return (f >= 0 ? (int)f : (int)f - 1); } 269 | 270 | [MethodImplAttribute(FN_INLINE)] 271 | private static int FastRound(FN_DECIMAL f) { return (f >= 0) ? (int)(f + (FN_DECIMAL)0.5) : (int)(f - (FN_DECIMAL)0.5); } 272 | 273 | [MethodImplAttribute(FN_INLINE)] 274 | private static FN_DECIMAL Lerp(FN_DECIMAL a, FN_DECIMAL b, FN_DECIMAL t) { return a + t * (b - a); } 275 | 276 | [MethodImplAttribute(FN_INLINE)] 277 | private static FN_DECIMAL InterpHermiteFunc(FN_DECIMAL t) { return t * t * (3 - 2 * t); } 278 | 279 | [MethodImplAttribute(FN_INLINE)] 280 | private static FN_DECIMAL InterpQuinticFunc(FN_DECIMAL t) { return t * t * t * (t * (t * 6 - 15) + 10); } 281 | 282 | [MethodImplAttribute(FN_INLINE)] 283 | private static FN_DECIMAL CubicLerp(FN_DECIMAL a, FN_DECIMAL b, FN_DECIMAL c, FN_DECIMAL d, FN_DECIMAL t) 284 | { 285 | FN_DECIMAL p = (d - c) - (a - b); 286 | return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b; 287 | } 288 | 289 | private void CalculateFractalBounding() 290 | { 291 | FN_DECIMAL amp = m_gain; 292 | FN_DECIMAL ampFractal = 1; 293 | for (int i = 1; i < m_octaves; i++) 294 | { 295 | ampFractal += amp; 296 | amp *= m_gain; 297 | } 298 | m_fractalBounding = 1 / ampFractal; 299 | } 300 | 301 | // Hashing 302 | private const int X_PRIME = 1619; 303 | private const int Y_PRIME = 31337; 304 | private const int Z_PRIME = 6971; 305 | private const int W_PRIME = 1013; 306 | 307 | [MethodImplAttribute(FN_INLINE)] 308 | private static int Hash2D(int seed, int x, int y) 309 | { 310 | int hash = seed; 311 | hash ^= X_PRIME * x; 312 | hash ^= Y_PRIME * y; 313 | 314 | hash = hash * hash * hash * 60493; 315 | hash = (hash >> 13) ^ hash; 316 | 317 | return hash; 318 | } 319 | 320 | [MethodImplAttribute(FN_INLINE)] 321 | private static int Hash3D(int seed, int x, int y, int z) 322 | { 323 | int hash = seed; 324 | hash ^= X_PRIME * x; 325 | hash ^= Y_PRIME * y; 326 | hash ^= Z_PRIME * z; 327 | 328 | hash = hash * hash * hash * 60493; 329 | hash = (hash >> 13) ^ hash; 330 | 331 | return hash; 332 | } 333 | 334 | [MethodImplAttribute(FN_INLINE)] 335 | private static int Hash4D(int seed, int x, int y, int z, int w) 336 | { 337 | int hash = seed; 338 | hash ^= X_PRIME * x; 339 | hash ^= Y_PRIME * y; 340 | hash ^= Z_PRIME * z; 341 | hash ^= W_PRIME * w; 342 | 343 | hash = hash * hash * hash * 60493; 344 | hash = (hash >> 13) ^ hash; 345 | 346 | return hash; 347 | } 348 | 349 | [MethodImplAttribute(FN_INLINE)] 350 | private static FN_DECIMAL ValCoord2D(int seed, int x, int y) 351 | { 352 | int n = seed; 353 | n ^= X_PRIME * x; 354 | n ^= Y_PRIME * y; 355 | 356 | return (n * n * n * 60493) / (FN_DECIMAL)2147483648.0; 357 | } 358 | 359 | [MethodImplAttribute(FN_INLINE)] 360 | private static FN_DECIMAL ValCoord3D(int seed, int x, int y, int z) 361 | { 362 | int n = seed; 363 | n ^= X_PRIME * x; 364 | n ^= Y_PRIME * y; 365 | n ^= Z_PRIME * z; 366 | 367 | return (n * n * n * 60493) / (FN_DECIMAL)2147483648.0; 368 | } 369 | 370 | [MethodImplAttribute(FN_INLINE)] 371 | private static FN_DECIMAL ValCoord4D(int seed, int x, int y, int z, int w) 372 | { 373 | int n = seed; 374 | n ^= X_PRIME * x; 375 | n ^= Y_PRIME * y; 376 | n ^= Z_PRIME * z; 377 | n ^= W_PRIME * w; 378 | 379 | return (n * n * n * 60493) / (FN_DECIMAL)2147483648.0; 380 | } 381 | 382 | [MethodImplAttribute(FN_INLINE)] 383 | private static FN_DECIMAL GradCoord2D(int seed, int x, int y, FN_DECIMAL xd, FN_DECIMAL yd) 384 | { 385 | int hash = seed; 386 | hash ^= X_PRIME * x; 387 | hash ^= Y_PRIME * y; 388 | 389 | hash = hash * hash * hash * 60493; 390 | hash = (hash >> 13) ^ hash; 391 | 392 | Float2 g = GRAD_2D[hash & 7]; 393 | 394 | return xd * g.x + yd * g.y; 395 | } 396 | 397 | [MethodImplAttribute(FN_INLINE)] 398 | private static FN_DECIMAL GradCoord3D(int seed, int x, int y, int z, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd) 399 | { 400 | int hash = seed; 401 | hash ^= X_PRIME * x; 402 | hash ^= Y_PRIME * y; 403 | hash ^= Z_PRIME * z; 404 | 405 | hash = hash * hash * hash * 60493; 406 | hash = (hash >> 13) ^ hash; 407 | 408 | Float3 g = GRAD_3D[hash & 15]; 409 | 410 | return xd * g.x + yd * g.y + zd * g.z; 411 | } 412 | 413 | [MethodImplAttribute(FN_INLINE)] 414 | 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) 415 | { 416 | int hash = seed; 417 | hash ^= X_PRIME * x; 418 | hash ^= Y_PRIME * y; 419 | hash ^= Z_PRIME * z; 420 | hash ^= W_PRIME * w; 421 | 422 | hash = hash * hash * hash * 60493; 423 | hash = (hash >> 13) ^ hash; 424 | 425 | hash &= 31; 426 | FN_DECIMAL a = yd, b = zd, c = wd; // X,Y,Z 427 | switch (hash >> 3) 428 | { // OR, DEPENDING ON HIGH ORDER 2 BITS: 429 | case 1: a = wd; b = xd; c = yd; break; // W,X,Y 430 | case 2: a = zd; b = wd; c = xd; break; // Z,W,X 431 | case 3: a = yd; b = zd; c = wd; break; // Y,Z,W 432 | } 433 | return ((hash & 4) == 0 ? -a : a) + ((hash & 2) == 0 ? -b : b) + ((hash & 1) == 0 ? -c : c); 434 | } 435 | 436 | public FN_DECIMAL GetNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 437 | { 438 | x *= m_frequency; 439 | y *= m_frequency; 440 | z *= m_frequency; 441 | 442 | switch (m_noiseType) 443 | { 444 | case NoiseType.Value: 445 | return SingleValue(m_seed, x, y, z); 446 | case NoiseType.ValueFractal: 447 | switch (m_fractalType) 448 | { 449 | case FractalType.FBM: 450 | return SingleValueFractalFBM(x, y, z); 451 | case FractalType.Billow: 452 | return SingleValueFractalBillow(x, y, z); 453 | case FractalType.RigidMulti: 454 | return SingleValueFractalRigidMulti(x, y, z); 455 | default: 456 | return 0; 457 | } 458 | case NoiseType.Perlin: 459 | return SinglePerlin(m_seed, x, y, z); 460 | case NoiseType.PerlinFractal: 461 | switch (m_fractalType) 462 | { 463 | case FractalType.FBM: 464 | return SinglePerlinFractalFBM(x, y, z); 465 | case FractalType.Billow: 466 | return SinglePerlinFractalBillow(x, y, z); 467 | case FractalType.RigidMulti: 468 | return SinglePerlinFractalRigidMulti(x, y, z); 469 | default: 470 | return 0; 471 | } 472 | case NoiseType.Simplex: 473 | return SingleSimplex(m_seed, x, y, z); 474 | case NoiseType.SimplexFractal: 475 | switch (m_fractalType) 476 | { 477 | case FractalType.FBM: 478 | return SingleSimplexFractalFBM(x, y, z); 479 | case FractalType.Billow: 480 | return SingleSimplexFractalBillow(x, y, z); 481 | case FractalType.RigidMulti: 482 | return SingleSimplexFractalRigidMulti(x, y, z); 483 | default: 484 | return 0; 485 | } 486 | case NoiseType.Cellular: 487 | switch (m_cellularReturnType) 488 | { 489 | case CellularReturnType.CellValue: 490 | case CellularReturnType.NoiseLookup: 491 | case CellularReturnType.Distance: 492 | return SingleCellular(x, y, z); 493 | default: 494 | return SingleCellular2Edge(x, y, z); 495 | } 496 | case NoiseType.WhiteNoise: 497 | return GetWhiteNoise(x, y, z); 498 | case NoiseType.Cubic: 499 | return SingleCubic(m_seed, x, y, z); 500 | case NoiseType.CubicFractal: 501 | switch (m_fractalType) 502 | { 503 | case FractalType.FBM: 504 | return SingleCubicFractalFBM(x, y, z); 505 | case FractalType.Billow: 506 | return SingleCubicFractalBillow(x, y, z); 507 | case FractalType.RigidMulti: 508 | return SingleCubicFractalRigidMulti(x, y, z); 509 | default: 510 | return 0; 511 | } 512 | default: 513 | return 0; 514 | } 515 | } 516 | 517 | public FN_DECIMAL GetNoise(FN_DECIMAL x, FN_DECIMAL y) 518 | { 519 | x *= m_frequency; 520 | y *= m_frequency; 521 | 522 | switch (m_noiseType) 523 | { 524 | case NoiseType.Value: 525 | return SingleValue(m_seed, x, y); 526 | case NoiseType.ValueFractal: 527 | switch (m_fractalType) 528 | { 529 | case FractalType.FBM: 530 | return SingleValueFractalFBM(x, y); 531 | case FractalType.Billow: 532 | return SingleValueFractalBillow(x, y); 533 | case FractalType.RigidMulti: 534 | return SingleValueFractalRigidMulti(x, y); 535 | default: 536 | return 0; 537 | } 538 | case NoiseType.Perlin: 539 | return SinglePerlin(m_seed, x, y); 540 | case NoiseType.PerlinFractal: 541 | switch (m_fractalType) 542 | { 543 | case FractalType.FBM: 544 | return SinglePerlinFractalFBM(x, y); 545 | case FractalType.Billow: 546 | return SinglePerlinFractalBillow(x, y); 547 | case FractalType.RigidMulti: 548 | return SinglePerlinFractalRigidMulti(x, y); 549 | default: 550 | return 0; 551 | } 552 | case NoiseType.Simplex: 553 | return SingleSimplex(m_seed, x, y); 554 | case NoiseType.SimplexFractal: 555 | switch (m_fractalType) 556 | { 557 | case FractalType.FBM: 558 | return SingleSimplexFractalFBM(x, y); 559 | case FractalType.Billow: 560 | return SingleSimplexFractalBillow(x, y); 561 | case FractalType.RigidMulti: 562 | return SingleSimplexFractalRigidMulti(x, y); 563 | default: 564 | return 0; 565 | } 566 | case NoiseType.Cellular: 567 | switch (m_cellularReturnType) 568 | { 569 | case CellularReturnType.CellValue: 570 | case CellularReturnType.NoiseLookup: 571 | case CellularReturnType.Distance: 572 | return SingleCellular(x, y); 573 | default: 574 | return SingleCellular2Edge(x, y); 575 | } 576 | case NoiseType.WhiteNoise: 577 | return GetWhiteNoise(x, y); 578 | case NoiseType.Cubic: 579 | return SingleCubic(m_seed, x, y); 580 | case NoiseType.CubicFractal: 581 | switch (m_fractalType) 582 | { 583 | case FractalType.FBM: 584 | return SingleCubicFractalFBM(x, y); 585 | case FractalType.Billow: 586 | return SingleCubicFractalBillow(x, y); 587 | case FractalType.RigidMulti: 588 | return SingleCubicFractalRigidMulti(x, y); 589 | default: 590 | return 0; 591 | } 592 | default: 593 | return 0; 594 | } 595 | } 596 | 597 | // White Noise 598 | [MethodImplAttribute(FN_INLINE)] 599 | private int FloatCast2Int(FN_DECIMAL f) 600 | { 601 | var i = BitConverter.DoubleToInt64Bits(f); 602 | 603 | return (int)(i ^ (i >> 32)); 604 | } 605 | 606 | public FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) 607 | { 608 | int xi = FloatCast2Int(x); 609 | int yi = FloatCast2Int(y); 610 | int zi = FloatCast2Int(z); 611 | int wi = FloatCast2Int(w); 612 | 613 | return ValCoord4D(m_seed, xi, yi, zi, wi); 614 | } 615 | 616 | public FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 617 | { 618 | int xi = FloatCast2Int(x); 619 | int yi = FloatCast2Int(y); 620 | int zi = FloatCast2Int(z); 621 | 622 | return ValCoord3D(m_seed, xi, yi, zi); 623 | } 624 | 625 | public FN_DECIMAL GetWhiteNoise(FN_DECIMAL x, FN_DECIMAL y) 626 | { 627 | int xi = FloatCast2Int(x); 628 | int yi = FloatCast2Int(y); 629 | 630 | return ValCoord2D(m_seed, xi, yi); 631 | } 632 | 633 | public FN_DECIMAL GetWhiteNoiseInt(int x, int y, int z, int w) 634 | { 635 | return ValCoord4D(m_seed, x, y, z, w); 636 | } 637 | 638 | public FN_DECIMAL GetWhiteNoiseInt(int x, int y, int z) 639 | { 640 | return ValCoord3D(m_seed, x, y, z); 641 | } 642 | 643 | public FN_DECIMAL GetWhiteNoiseInt(int x, int y) 644 | { 645 | return ValCoord2D(m_seed, x, y); 646 | } 647 | 648 | // Value Noise 649 | public FN_DECIMAL GetValueFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 650 | { 651 | x *= m_frequency; 652 | y *= m_frequency; 653 | z *= m_frequency; 654 | 655 | switch (m_fractalType) 656 | { 657 | case FractalType.FBM: 658 | return SingleValueFractalFBM(x, y, z); 659 | case FractalType.Billow: 660 | return SingleValueFractalBillow(x, y, z); 661 | case FractalType.RigidMulti: 662 | return SingleValueFractalRigidMulti(x, y, z); 663 | default: 664 | return 0; 665 | } 666 | } 667 | 668 | private FN_DECIMAL SingleValueFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 669 | { 670 | int seed = m_seed; 671 | FN_DECIMAL sum = SingleValue(seed, x, y, z); 672 | FN_DECIMAL amp = 1; 673 | 674 | for (int i = 1; i < m_octaves; i++) 675 | { 676 | x *= m_lacunarity; 677 | y *= m_lacunarity; 678 | z *= m_lacunarity; 679 | 680 | amp *= m_gain; 681 | sum += SingleValue(++seed, x, y, z) * amp; 682 | } 683 | 684 | return sum * m_fractalBounding; 685 | } 686 | 687 | private FN_DECIMAL SingleValueFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 688 | { 689 | int seed = m_seed; 690 | FN_DECIMAL sum = Math.Abs(SingleValue(seed, x, y, z)) * 2 - 1; 691 | FN_DECIMAL amp = 1; 692 | 693 | for (int i = 1; i < m_octaves; i++) 694 | { 695 | x *= m_lacunarity; 696 | y *= m_lacunarity; 697 | z *= m_lacunarity; 698 | 699 | amp *= m_gain; 700 | sum += (Math.Abs(SingleValue(++seed, x, y, z)) * 2 - 1) * amp; 701 | } 702 | 703 | return sum * m_fractalBounding; 704 | } 705 | 706 | private FN_DECIMAL SingleValueFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 707 | { 708 | int seed = m_seed; 709 | FN_DECIMAL sum = 1 - Math.Abs(SingleValue(seed, x, y, z)); 710 | FN_DECIMAL amp = 1; 711 | 712 | for (int i = 1; i < m_octaves; i++) 713 | { 714 | x *= m_lacunarity; 715 | y *= m_lacunarity; 716 | z *= m_lacunarity; 717 | 718 | amp *= m_gain; 719 | sum -= (1 - Math.Abs(SingleValue(++seed, x, y, z))) * amp; 720 | } 721 | 722 | return sum; 723 | } 724 | 725 | public FN_DECIMAL GetValue(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 726 | { 727 | return SingleValue(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); 728 | } 729 | 730 | private FN_DECIMAL SingleValue(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 731 | { 732 | int x0 = FastFloor(x); 733 | int y0 = FastFloor(y); 734 | int z0 = FastFloor(z); 735 | int x1 = x0 + 1; 736 | int y1 = y0 + 1; 737 | int z1 = z0 + 1; 738 | 739 | FN_DECIMAL xs, ys, zs; 740 | switch (m_interp) 741 | { 742 | default: 743 | case Interp.Linear: 744 | xs = x - x0; 745 | ys = y - y0; 746 | zs = z - z0; 747 | break; 748 | case Interp.Hermite: 749 | xs = InterpHermiteFunc(x - x0); 750 | ys = InterpHermiteFunc(y - y0); 751 | zs = InterpHermiteFunc(z - z0); 752 | break; 753 | case Interp.Quintic: 754 | xs = InterpQuinticFunc(x - x0); 755 | ys = InterpQuinticFunc(y - y0); 756 | zs = InterpQuinticFunc(z - z0); 757 | break; 758 | } 759 | 760 | FN_DECIMAL xf00 = Lerp(ValCoord3D(seed, x0, y0, z0), ValCoord3D(seed, x1, y0, z0), xs); 761 | FN_DECIMAL xf10 = Lerp(ValCoord3D(seed, x0, y1, z0), ValCoord3D(seed, x1, y1, z0), xs); 762 | FN_DECIMAL xf01 = Lerp(ValCoord3D(seed, x0, y0, z1), ValCoord3D(seed, x1, y0, z1), xs); 763 | FN_DECIMAL xf11 = Lerp(ValCoord3D(seed, x0, y1, z1), ValCoord3D(seed, x1, y1, z1), xs); 764 | 765 | FN_DECIMAL yf0 = Lerp(xf00, xf10, ys); 766 | FN_DECIMAL yf1 = Lerp(xf01, xf11, ys); 767 | 768 | return Lerp(yf0, yf1, zs); 769 | } 770 | 771 | public FN_DECIMAL GetValueFractal(FN_DECIMAL x, FN_DECIMAL y) 772 | { 773 | x *= m_frequency; 774 | y *= m_frequency; 775 | 776 | switch (m_fractalType) 777 | { 778 | case FractalType.FBM: 779 | return SingleValueFractalFBM(x, y); 780 | case FractalType.Billow: 781 | return SingleValueFractalBillow(x, y); 782 | case FractalType.RigidMulti: 783 | return SingleValueFractalRigidMulti(x, y); 784 | default: 785 | return 0; 786 | } 787 | } 788 | 789 | private FN_DECIMAL SingleValueFractalFBM(FN_DECIMAL x, FN_DECIMAL y) 790 | { 791 | int seed = m_seed; 792 | FN_DECIMAL sum = SingleValue(seed, x, y); 793 | FN_DECIMAL amp = 1; 794 | 795 | for (int i = 1; i < m_octaves; i++) 796 | { 797 | x *= m_lacunarity; 798 | y *= m_lacunarity; 799 | 800 | amp *= m_gain; 801 | sum += SingleValue(++seed, x, y) * amp; 802 | } 803 | 804 | return sum * m_fractalBounding; 805 | } 806 | 807 | private FN_DECIMAL SingleValueFractalBillow(FN_DECIMAL x, FN_DECIMAL y) 808 | { 809 | int seed = m_seed; 810 | FN_DECIMAL sum = Math.Abs(SingleValue(seed, x, y)) * 2 - 1; 811 | FN_DECIMAL amp = 1; 812 | 813 | for (int i = 1; i < m_octaves; i++) 814 | { 815 | x *= m_lacunarity; 816 | y *= m_lacunarity; 817 | amp *= m_gain; 818 | sum += (Math.Abs(SingleValue(++seed, x, y)) * 2 - 1) * amp; 819 | } 820 | 821 | return sum * m_fractalBounding; 822 | } 823 | 824 | private FN_DECIMAL SingleValueFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) 825 | { 826 | int seed = m_seed; 827 | FN_DECIMAL sum = 1 - Math.Abs(SingleValue(seed, x, y)); 828 | FN_DECIMAL amp = 1; 829 | 830 | for (int i = 1; i < m_octaves; i++) 831 | { 832 | x *= m_lacunarity; 833 | y *= m_lacunarity; 834 | 835 | amp *= m_gain; 836 | sum -= (1 - Math.Abs(SingleValue(++seed, x, y))) * amp; 837 | } 838 | 839 | return sum; 840 | } 841 | 842 | public FN_DECIMAL GetValue(FN_DECIMAL x, FN_DECIMAL y) 843 | { 844 | return SingleValue(m_seed, x * m_frequency, y * m_frequency); 845 | } 846 | 847 | private FN_DECIMAL SingleValue(int seed, FN_DECIMAL x, FN_DECIMAL y) 848 | { 849 | int x0 = FastFloor(x); 850 | int y0 = FastFloor(y); 851 | int x1 = x0 + 1; 852 | int y1 = y0 + 1; 853 | 854 | FN_DECIMAL xs, ys; 855 | switch (m_interp) 856 | { 857 | default: 858 | case Interp.Linear: 859 | xs = x - x0; 860 | ys = y - y0; 861 | break; 862 | case Interp.Hermite: 863 | xs = InterpHermiteFunc(x - x0); 864 | ys = InterpHermiteFunc(y - y0); 865 | break; 866 | case Interp.Quintic: 867 | xs = InterpQuinticFunc(x - x0); 868 | ys = InterpQuinticFunc(y - y0); 869 | break; 870 | } 871 | 872 | FN_DECIMAL xf0 = Lerp(ValCoord2D(seed, x0, y0), ValCoord2D(seed, x1, y0), xs); 873 | FN_DECIMAL xf1 = Lerp(ValCoord2D(seed, x0, y1), ValCoord2D(seed, x1, y1), xs); 874 | 875 | return Lerp(xf0, xf1, ys); 876 | } 877 | 878 | // Gradient Noise 879 | public FN_DECIMAL GetPerlinFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 880 | { 881 | x *= m_frequency; 882 | y *= m_frequency; 883 | z *= m_frequency; 884 | 885 | switch (m_fractalType) 886 | { 887 | case FractalType.FBM: 888 | return SinglePerlinFractalFBM(x, y, z); 889 | case FractalType.Billow: 890 | return SinglePerlinFractalBillow(x, y, z); 891 | case FractalType.RigidMulti: 892 | return SinglePerlinFractalRigidMulti(x, y, z); 893 | default: 894 | return 0; 895 | } 896 | } 897 | 898 | private FN_DECIMAL SinglePerlinFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 899 | { 900 | int seed = m_seed; 901 | FN_DECIMAL sum = SinglePerlin(seed, x, y, z); 902 | FN_DECIMAL amp = 1; 903 | 904 | for (int i = 1; i < m_octaves; i++) 905 | { 906 | x *= m_lacunarity; 907 | y *= m_lacunarity; 908 | z *= m_lacunarity; 909 | 910 | amp *= m_gain; 911 | sum += SinglePerlin(++seed, x, y, z) * amp; 912 | } 913 | 914 | return sum * m_fractalBounding; 915 | } 916 | 917 | private FN_DECIMAL SinglePerlinFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 918 | { 919 | int seed = m_seed; 920 | FN_DECIMAL sum = Math.Abs(SinglePerlin(seed, x, y, z)) * 2 - 1; 921 | FN_DECIMAL amp = 1; 922 | 923 | for (int i = 1; i < m_octaves; i++) 924 | { 925 | x *= m_lacunarity; 926 | y *= m_lacunarity; 927 | z *= m_lacunarity; 928 | 929 | amp *= m_gain; 930 | sum += (Math.Abs(SinglePerlin(++seed, x, y, z)) * 2 - 1) * amp; 931 | } 932 | 933 | return sum * m_fractalBounding; 934 | } 935 | 936 | private FN_DECIMAL SinglePerlinFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 937 | { 938 | int seed = m_seed; 939 | FN_DECIMAL sum = 1 - Math.Abs(SinglePerlin(seed, x, y, z)); 940 | FN_DECIMAL amp = 1; 941 | 942 | for (int i = 1; i < m_octaves; i++) 943 | { 944 | x *= m_lacunarity; 945 | y *= m_lacunarity; 946 | z *= m_lacunarity; 947 | 948 | amp *= m_gain; 949 | sum -= (1 - Math.Abs(SinglePerlin(++seed, x, y, z))) * amp; 950 | } 951 | 952 | return sum; 953 | } 954 | 955 | public FN_DECIMAL GetPerlin(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 956 | { 957 | return SinglePerlin(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); 958 | } 959 | 960 | private FN_DECIMAL SinglePerlin(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 961 | { 962 | int x0 = FastFloor(x); 963 | int y0 = FastFloor(y); 964 | int z0 = FastFloor(z); 965 | int x1 = x0 + 1; 966 | int y1 = y0 + 1; 967 | int z1 = z0 + 1; 968 | 969 | FN_DECIMAL xs, ys, zs; 970 | switch (m_interp) 971 | { 972 | default: 973 | case Interp.Linear: 974 | xs = x - x0; 975 | ys = y - y0; 976 | zs = z - z0; 977 | break; 978 | case Interp.Hermite: 979 | xs = InterpHermiteFunc(x - x0); 980 | ys = InterpHermiteFunc(y - y0); 981 | zs = InterpHermiteFunc(z - z0); 982 | break; 983 | case Interp.Quintic: 984 | xs = InterpQuinticFunc(x - x0); 985 | ys = InterpQuinticFunc(y - y0); 986 | zs = InterpQuinticFunc(z - z0); 987 | break; 988 | } 989 | 990 | FN_DECIMAL xd0 = x - x0; 991 | FN_DECIMAL yd0 = y - y0; 992 | FN_DECIMAL zd0 = z - z0; 993 | FN_DECIMAL xd1 = xd0 - 1; 994 | FN_DECIMAL yd1 = yd0 - 1; 995 | FN_DECIMAL zd1 = zd0 - 1; 996 | 997 | FN_DECIMAL xf00 = Lerp(GradCoord3D(seed, x0, y0, z0, xd0, yd0, zd0), GradCoord3D(seed, x1, y0, z0, xd1, yd0, zd0), xs); 998 | FN_DECIMAL xf10 = Lerp(GradCoord3D(seed, x0, y1, z0, xd0, yd1, zd0), GradCoord3D(seed, x1, y1, z0, xd1, yd1, zd0), xs); 999 | FN_DECIMAL xf01 = Lerp(GradCoord3D(seed, x0, y0, z1, xd0, yd0, zd1), GradCoord3D(seed, x1, y0, z1, xd1, yd0, zd1), xs); 1000 | FN_DECIMAL xf11 = Lerp(GradCoord3D(seed, x0, y1, z1, xd0, yd1, zd1), GradCoord3D(seed, x1, y1, z1, xd1, yd1, zd1), xs); 1001 | 1002 | FN_DECIMAL yf0 = Lerp(xf00, xf10, ys); 1003 | FN_DECIMAL yf1 = Lerp(xf01, xf11, ys); 1004 | 1005 | return Lerp(yf0, yf1, zs); 1006 | } 1007 | 1008 | public FN_DECIMAL GetPerlinFractal(FN_DECIMAL x, FN_DECIMAL y) 1009 | { 1010 | x *= m_frequency; 1011 | y *= m_frequency; 1012 | 1013 | switch (m_fractalType) 1014 | { 1015 | case FractalType.FBM: 1016 | return SinglePerlinFractalFBM(x, y); 1017 | case FractalType.Billow: 1018 | return SinglePerlinFractalBillow(x, y); 1019 | case FractalType.RigidMulti: 1020 | return SinglePerlinFractalRigidMulti(x, y); 1021 | default: 1022 | return 0; 1023 | } 1024 | } 1025 | 1026 | private FN_DECIMAL SinglePerlinFractalFBM(FN_DECIMAL x, FN_DECIMAL y) 1027 | { 1028 | int seed = m_seed; 1029 | FN_DECIMAL sum = SinglePerlin(seed, x, y); 1030 | FN_DECIMAL amp = 1; 1031 | 1032 | for (int i = 1; i < m_octaves; i++) 1033 | { 1034 | x *= m_lacunarity; 1035 | y *= m_lacunarity; 1036 | 1037 | amp *= m_gain; 1038 | sum += SinglePerlin(++seed, x, y) * amp; 1039 | } 1040 | 1041 | return sum * m_fractalBounding; 1042 | } 1043 | 1044 | private FN_DECIMAL SinglePerlinFractalBillow(FN_DECIMAL x, FN_DECIMAL y) 1045 | { 1046 | int seed = m_seed; 1047 | FN_DECIMAL sum = Math.Abs(SinglePerlin(seed, x, y)) * 2 - 1; 1048 | FN_DECIMAL amp = 1; 1049 | 1050 | for (int i = 1; i < m_octaves; i++) 1051 | { 1052 | x *= m_lacunarity; 1053 | y *= m_lacunarity; 1054 | 1055 | amp *= m_gain; 1056 | sum += (Math.Abs(SinglePerlin(++seed, x, y)) * 2 - 1) * amp; 1057 | } 1058 | 1059 | return sum * m_fractalBounding; 1060 | } 1061 | 1062 | private FN_DECIMAL SinglePerlinFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) 1063 | { 1064 | int seed = m_seed; 1065 | FN_DECIMAL sum = 1 - Math.Abs(SinglePerlin(seed, x, y)); 1066 | FN_DECIMAL amp = 1; 1067 | 1068 | for (int i = 1; i < m_octaves; i++) 1069 | { 1070 | x *= m_lacunarity; 1071 | y *= m_lacunarity; 1072 | 1073 | amp *= m_gain; 1074 | sum -= (1 - Math.Abs(SinglePerlin(++seed, x, y))) * amp; 1075 | } 1076 | 1077 | return sum; 1078 | } 1079 | 1080 | public FN_DECIMAL GetPerlin(FN_DECIMAL x, FN_DECIMAL y) 1081 | { 1082 | return SinglePerlin(m_seed, x * m_frequency, y * m_frequency); 1083 | } 1084 | 1085 | private FN_DECIMAL SinglePerlin(int seed, FN_DECIMAL x, FN_DECIMAL y) 1086 | { 1087 | int x0 = FastFloor(x); 1088 | int y0 = FastFloor(y); 1089 | int x1 = x0 + 1; 1090 | int y1 = y0 + 1; 1091 | 1092 | FN_DECIMAL xs, ys; 1093 | switch (m_interp) 1094 | { 1095 | default: 1096 | case Interp.Linear: 1097 | xs = x - x0; 1098 | ys = y - y0; 1099 | break; 1100 | case Interp.Hermite: 1101 | xs = InterpHermiteFunc(x - x0); 1102 | ys = InterpHermiteFunc(y - y0); 1103 | break; 1104 | case Interp.Quintic: 1105 | xs = InterpQuinticFunc(x - x0); 1106 | ys = InterpQuinticFunc(y - y0); 1107 | break; 1108 | } 1109 | 1110 | FN_DECIMAL xd0 = x - x0; 1111 | FN_DECIMAL yd0 = y - y0; 1112 | FN_DECIMAL xd1 = xd0 - 1; 1113 | FN_DECIMAL yd1 = yd0 - 1; 1114 | 1115 | FN_DECIMAL xf0 = Lerp(GradCoord2D(seed, x0, y0, xd0, yd0), GradCoord2D(seed, x1, y0, xd1, yd0), xs); 1116 | FN_DECIMAL xf1 = Lerp(GradCoord2D(seed, x0, y1, xd0, yd1), GradCoord2D(seed, x1, y1, xd1, yd1), xs); 1117 | 1118 | return Lerp(xf0, xf1, ys); 1119 | } 1120 | 1121 | // Simplex Noise 1122 | public FN_DECIMAL GetSimplexFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1123 | { 1124 | x *= m_frequency; 1125 | y *= m_frequency; 1126 | z *= m_frequency; 1127 | 1128 | switch (m_fractalType) 1129 | { 1130 | case FractalType.FBM: 1131 | return SingleSimplexFractalFBM(x, y, z); 1132 | case FractalType.Billow: 1133 | return SingleSimplexFractalBillow(x, y, z); 1134 | case FractalType.RigidMulti: 1135 | return SingleSimplexFractalRigidMulti(x, y, z); 1136 | default: 1137 | return 0; 1138 | } 1139 | } 1140 | 1141 | private FN_DECIMAL SingleSimplexFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1142 | { 1143 | int seed = m_seed; 1144 | FN_DECIMAL sum = SingleSimplex(seed, x, y, z); 1145 | FN_DECIMAL amp = 1; 1146 | 1147 | for (int i = 1; i < m_octaves; i++) 1148 | { 1149 | x *= m_lacunarity; 1150 | y *= m_lacunarity; 1151 | z *= m_lacunarity; 1152 | 1153 | amp *= m_gain; 1154 | sum += SingleSimplex(++seed, x, y, z) * amp; 1155 | } 1156 | 1157 | return sum * m_fractalBounding; 1158 | } 1159 | 1160 | private FN_DECIMAL SingleSimplexFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1161 | { 1162 | int seed = m_seed; 1163 | FN_DECIMAL sum = Math.Abs(SingleSimplex(seed, x, y, z)) * 2 - 1; 1164 | FN_DECIMAL amp = 1; 1165 | 1166 | for (int i = 1; i < m_octaves; i++) 1167 | { 1168 | x *= m_lacunarity; 1169 | y *= m_lacunarity; 1170 | z *= m_lacunarity; 1171 | 1172 | amp *= m_gain; 1173 | sum += (Math.Abs(SingleSimplex(++seed, x, y, z)) * 2 - 1) * amp; 1174 | } 1175 | 1176 | return sum * m_fractalBounding; 1177 | } 1178 | 1179 | private FN_DECIMAL SingleSimplexFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1180 | { 1181 | int seed = m_seed; 1182 | FN_DECIMAL sum = 1 - Math.Abs(SingleSimplex(seed, x, y, z)); 1183 | FN_DECIMAL amp = 1; 1184 | 1185 | for (int i = 1; i < m_octaves; i++) 1186 | { 1187 | x *= m_lacunarity; 1188 | y *= m_lacunarity; 1189 | z *= m_lacunarity; 1190 | 1191 | amp *= m_gain; 1192 | sum -= (1 - Math.Abs(SingleSimplex(++seed, x, y, z))) * amp; 1193 | } 1194 | 1195 | return sum; 1196 | } 1197 | 1198 | public FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1199 | { 1200 | return SingleSimplex(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); 1201 | } 1202 | 1203 | private const FN_DECIMAL F3 = (FN_DECIMAL)(1.0 / 3.0); 1204 | private const FN_DECIMAL G3 = (FN_DECIMAL)(1.0 / 6.0); 1205 | private const FN_DECIMAL G33 = G3 * 3 - 1; 1206 | 1207 | private FN_DECIMAL SingleSimplex(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1208 | { 1209 | FN_DECIMAL t = (x + y + z) * F3; 1210 | int i = FastFloor(x + t); 1211 | int j = FastFloor(y + t); 1212 | int k = FastFloor(z + t); 1213 | 1214 | t = (i + j + k) * G3; 1215 | FN_DECIMAL x0 = x - (i - t); 1216 | FN_DECIMAL y0 = y - (j - t); 1217 | FN_DECIMAL z0 = z - (k - t); 1218 | 1219 | int i1, j1, k1; 1220 | int i2, j2, k2; 1221 | 1222 | if (x0 >= y0) 1223 | { 1224 | if (y0 >= z0) 1225 | { 1226 | i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; 1227 | } 1228 | else if (x0 >= z0) 1229 | { 1230 | i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; 1231 | } 1232 | else // x0 < z0 1233 | { 1234 | i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; 1235 | } 1236 | } 1237 | else // x0 < y0 1238 | { 1239 | if (y0 < z0) 1240 | { 1241 | i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; 1242 | } 1243 | else if (x0 < z0) 1244 | { 1245 | i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; 1246 | } 1247 | else // x0 >= z0 1248 | { 1249 | i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; 1250 | } 1251 | } 1252 | 1253 | FN_DECIMAL x1 = x0 - i1 + G3; 1254 | FN_DECIMAL y1 = y0 - j1 + G3; 1255 | FN_DECIMAL z1 = z0 - k1 + G3; 1256 | FN_DECIMAL x2 = x0 - i2 + F3; 1257 | FN_DECIMAL y2 = y0 - j2 + F3; 1258 | FN_DECIMAL z2 = z0 - k2 + F3; 1259 | FN_DECIMAL x3 = x0 + G33; 1260 | FN_DECIMAL y3 = y0 + G33; 1261 | FN_DECIMAL z3 = z0 + G33; 1262 | 1263 | FN_DECIMAL n0, n1, n2, n3; 1264 | 1265 | t = (FN_DECIMAL)0.6 - x0 * x0 - y0 * y0 - z0 * z0; 1266 | if (t < 0) n0 = 0; 1267 | else 1268 | { 1269 | t *= t; 1270 | n0 = t * t * GradCoord3D(seed, i, j, k, x0, y0, z0); 1271 | } 1272 | 1273 | t = (FN_DECIMAL)0.6 - x1 * x1 - y1 * y1 - z1 * z1; 1274 | if (t < 0) n1 = 0; 1275 | else 1276 | { 1277 | t *= t; 1278 | n1 = t * t * GradCoord3D(seed, i + i1, j + j1, k + k1, x1, y1, z1); 1279 | } 1280 | 1281 | t = (FN_DECIMAL)0.6 - x2 * x2 - y2 * y2 - z2 * z2; 1282 | if (t < 0) n2 = 0; 1283 | else 1284 | { 1285 | t *= t; 1286 | n2 = t * t * GradCoord3D(seed, i + i2, j + j2, k + k2, x2, y2, z2); 1287 | } 1288 | 1289 | t = (FN_DECIMAL)0.6 - x3 * x3 - y3 * y3 - z3 * z3; 1290 | if (t < 0) n3 = 0; 1291 | else 1292 | { 1293 | t *= t; 1294 | n3 = t * t * GradCoord3D(seed, i + 1, j + 1, k + 1, x3, y3, z3); 1295 | } 1296 | 1297 | return 32 * (n0 + n1 + n2 + n3); 1298 | } 1299 | 1300 | public FN_DECIMAL GetSimplexFractal(FN_DECIMAL x, FN_DECIMAL y) 1301 | { 1302 | x *= m_frequency; 1303 | y *= m_frequency; 1304 | 1305 | switch (m_fractalType) 1306 | { 1307 | case FractalType.FBM: 1308 | return SingleSimplexFractalFBM(x, y); 1309 | case FractalType.Billow: 1310 | return SingleSimplexFractalBillow(x, y); 1311 | case FractalType.RigidMulti: 1312 | return SingleSimplexFractalRigidMulti(x, y); 1313 | default: 1314 | return 0; 1315 | } 1316 | } 1317 | 1318 | private FN_DECIMAL SingleSimplexFractalFBM(FN_DECIMAL x, FN_DECIMAL y) 1319 | { 1320 | int seed = m_seed; 1321 | FN_DECIMAL sum = SingleSimplex(seed, x, y); 1322 | FN_DECIMAL amp = 1; 1323 | 1324 | for (int i = 1; i < m_octaves; i++) 1325 | { 1326 | x *= m_lacunarity; 1327 | y *= m_lacunarity; 1328 | 1329 | amp *= m_gain; 1330 | sum += SingleSimplex(++seed, x, y) * amp; 1331 | } 1332 | 1333 | return sum * m_fractalBounding; 1334 | } 1335 | 1336 | private FN_DECIMAL SingleSimplexFractalBillow(FN_DECIMAL x, FN_DECIMAL y) 1337 | { 1338 | int seed = m_seed; 1339 | FN_DECIMAL sum = Math.Abs(SingleSimplex(seed, x, y)) * 2 - 1; 1340 | FN_DECIMAL amp = 1; 1341 | 1342 | for (int i = 1; i < m_octaves; i++) 1343 | { 1344 | x *= m_lacunarity; 1345 | y *= m_lacunarity; 1346 | 1347 | amp *= m_gain; 1348 | sum += (Math.Abs(SingleSimplex(++seed, x, y)) * 2 - 1) * amp; 1349 | } 1350 | 1351 | return sum * m_fractalBounding; 1352 | } 1353 | 1354 | private FN_DECIMAL SingleSimplexFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) 1355 | { 1356 | int seed = m_seed; 1357 | FN_DECIMAL sum = 1 - Math.Abs(SingleSimplex(seed, x, y)); 1358 | FN_DECIMAL amp = 1; 1359 | 1360 | for (int i = 1; i < m_octaves; i++) 1361 | { 1362 | x *= m_lacunarity; 1363 | y *= m_lacunarity; 1364 | 1365 | amp *= m_gain; 1366 | sum -= (1 - Math.Abs(SingleSimplex(++seed, x, y))) * amp; 1367 | } 1368 | 1369 | return sum; 1370 | } 1371 | 1372 | public FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y) 1373 | { 1374 | return SingleSimplex(m_seed, x * m_frequency, y * m_frequency); 1375 | } 1376 | 1377 | private const FN_DECIMAL F2 = (FN_DECIMAL)(1.0 / 2.0); 1378 | private const FN_DECIMAL G2 = (FN_DECIMAL)(1.0 / 4.0); 1379 | 1380 | private FN_DECIMAL SingleSimplex(int seed, FN_DECIMAL x, FN_DECIMAL y) 1381 | { 1382 | FN_DECIMAL t = (x + y) * F2; 1383 | int i = FastFloor(x + t); 1384 | int j = FastFloor(y + t); 1385 | 1386 | t = (i + j) * G2; 1387 | FN_DECIMAL X0 = i - t; 1388 | FN_DECIMAL Y0 = j - t; 1389 | 1390 | FN_DECIMAL x0 = x - X0; 1391 | FN_DECIMAL y0 = y - Y0; 1392 | 1393 | int i1, j1; 1394 | if (x0 > y0) 1395 | { 1396 | i1 = 1; j1 = 0; 1397 | } 1398 | else 1399 | { 1400 | i1 = 0; j1 = 1; 1401 | } 1402 | 1403 | FN_DECIMAL x1 = x0 - i1 + G2; 1404 | FN_DECIMAL y1 = y0 - j1 + G2; 1405 | FN_DECIMAL x2 = x0 - 1 + F2; 1406 | FN_DECIMAL y2 = y0 - 1 + F2; 1407 | 1408 | FN_DECIMAL n0, n1, n2; 1409 | 1410 | t = (FN_DECIMAL)0.5 - x0 * x0 - y0 * y0; 1411 | if (t < 0) n0 = 0; 1412 | else 1413 | { 1414 | t *= t; 1415 | n0 = t * t * GradCoord2D(seed, i, j, x0, y0); 1416 | } 1417 | 1418 | t = (FN_DECIMAL)0.5 - x1 * x1 - y1 * y1; 1419 | if (t < 0) n1 = 0; 1420 | else 1421 | { 1422 | t *= t; 1423 | n1 = t * t * GradCoord2D(seed, i + i1, j + j1, x1, y1); 1424 | } 1425 | 1426 | t = (FN_DECIMAL)0.5 - x2 * x2 - y2 * y2; 1427 | if (t < 0) n2 = 0; 1428 | else 1429 | { 1430 | t *= t; 1431 | n2 = t * t * GradCoord2D(seed, i + 1, j + 1, x2, y2); 1432 | } 1433 | 1434 | return 50 * (n0 + n1 + n2); 1435 | } 1436 | 1437 | public FN_DECIMAL GetSimplex(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) 1438 | { 1439 | return SingleSimplex(m_seed, x * m_frequency, y * m_frequency, z * m_frequency, w * m_frequency); 1440 | } 1441 | 1442 | private static readonly byte[] SIMPLEX_4D = 1443 | { 1444 | 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, 1445 | 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, 1446 | 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, 1447 | 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, 1448 | 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, 1449 | 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, 1450 | 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, 1451 | 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 1452 | }; 1453 | 1454 | private const FN_DECIMAL F4 = (FN_DECIMAL)((2.23606797 - 1.0) / 4.0); 1455 | private const FN_DECIMAL G4 = (FN_DECIMAL)((5.0 - 2.23606797) / 20.0); 1456 | 1457 | private FN_DECIMAL SingleSimplex(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w) 1458 | { 1459 | FN_DECIMAL n0, n1, n2, n3, n4; 1460 | FN_DECIMAL t = (x + y + z + w) * F4; 1461 | int i = FastFloor(x + t); 1462 | int j = FastFloor(y + t); 1463 | int k = FastFloor(z + t); 1464 | int l = FastFloor(w + t); 1465 | t = (i + j + k + l) * G4; 1466 | FN_DECIMAL X0 = i - t; 1467 | FN_DECIMAL Y0 = j - t; 1468 | FN_DECIMAL Z0 = k - t; 1469 | FN_DECIMAL W0 = l - t; 1470 | FN_DECIMAL x0 = x - X0; 1471 | FN_DECIMAL y0 = y - Y0; 1472 | FN_DECIMAL z0 = z - Z0; 1473 | FN_DECIMAL w0 = w - W0; 1474 | 1475 | int c = (x0 > y0) ? 32 : 0; 1476 | c += (x0 > z0) ? 16 : 0; 1477 | c += (y0 > z0) ? 8 : 0; 1478 | c += (x0 > w0) ? 4 : 0; 1479 | c += (y0 > w0) ? 2 : 0; 1480 | c += (z0 > w0) ? 1 : 0; 1481 | c <<= 2; 1482 | 1483 | int i1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; 1484 | int i2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; 1485 | int i3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; 1486 | int j1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; 1487 | int j2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; 1488 | int j3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; 1489 | int k1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; 1490 | int k2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; 1491 | int k3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0; 1492 | int l1 = SIMPLEX_4D[c] >= 3 ? 1 : 0; 1493 | int l2 = SIMPLEX_4D[c] >= 2 ? 1 : 0; 1494 | int l3 = SIMPLEX_4D[c] >= 1 ? 1 : 0; 1495 | 1496 | FN_DECIMAL x1 = x0 - i1 + G4; 1497 | FN_DECIMAL y1 = y0 - j1 + G4; 1498 | FN_DECIMAL z1 = z0 - k1 + G4; 1499 | FN_DECIMAL w1 = w0 - l1 + G4; 1500 | FN_DECIMAL x2 = x0 - i2 + 2 * G4; 1501 | FN_DECIMAL y2 = y0 - j2 + 2 * G4; 1502 | FN_DECIMAL z2 = z0 - k2 + 2 * G4; 1503 | FN_DECIMAL w2 = w0 - l2 + 2 * G4; 1504 | FN_DECIMAL x3 = x0 - i3 + 3 * G4; 1505 | FN_DECIMAL y3 = y0 - j3 + 3 * G4; 1506 | FN_DECIMAL z3 = z0 - k3 + 3 * G4; 1507 | FN_DECIMAL w3 = w0 - l3 + 3 * G4; 1508 | FN_DECIMAL x4 = x0 - 1 + 4 * G4; 1509 | FN_DECIMAL y4 = y0 - 1 + 4 * G4; 1510 | FN_DECIMAL z4 = z0 - 1 + 4 * G4; 1511 | FN_DECIMAL w4 = w0 - 1 + 4 * G4; 1512 | 1513 | t = (FN_DECIMAL)0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0; 1514 | if (t < 0) n0 = 0; 1515 | else 1516 | { 1517 | t *= t; 1518 | n0 = t * t * GradCoord4D(seed, i, j, k, l, x0, y0, z0, w0); 1519 | } 1520 | t = (FN_DECIMAL)0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1; 1521 | if (t < 0) n1 = 0; 1522 | else 1523 | { 1524 | t *= t; 1525 | n1 = t * t * GradCoord4D(seed, i + i1, j + j1, k + k1, l + l1, x1, y1, z1, w1); 1526 | } 1527 | t = (FN_DECIMAL)0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2; 1528 | if (t < 0) n2 = 0; 1529 | else 1530 | { 1531 | t *= t; 1532 | n2 = t * t * GradCoord4D(seed, i + i2, j + j2, k + k2, l + l2, x2, y2, z2, w2); 1533 | } 1534 | t = (FN_DECIMAL)0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3; 1535 | if (t < 0) n3 = 0; 1536 | else 1537 | { 1538 | t *= t; 1539 | n3 = t * t * GradCoord4D(seed, i + i3, j + j3, k + k3, l + l3, x3, y3, z3, w3); 1540 | } 1541 | t = (FN_DECIMAL)0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4; 1542 | if (t < 0) n4 = 0; 1543 | else 1544 | { 1545 | t *= t; 1546 | n4 = t * t * GradCoord4D(seed, i + 1, j + 1, k + 1, l + 1, x4, y4, z4, w4); 1547 | } 1548 | 1549 | return 27 * (n0 + n1 + n2 + n3 + n4); 1550 | } 1551 | 1552 | // Cubic Noise 1553 | public FN_DECIMAL GetCubicFractal(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1554 | { 1555 | x *= m_frequency; 1556 | y *= m_frequency; 1557 | z *= m_frequency; 1558 | 1559 | switch (m_fractalType) 1560 | { 1561 | case FractalType.FBM: 1562 | return SingleCubicFractalFBM(x, y, z); 1563 | case FractalType.Billow: 1564 | return SingleCubicFractalBillow(x, y, z); 1565 | case FractalType.RigidMulti: 1566 | return SingleCubicFractalRigidMulti(x, y, z); 1567 | default: 1568 | return 0; 1569 | } 1570 | } 1571 | 1572 | private FN_DECIMAL SingleCubicFractalFBM(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1573 | { 1574 | int seed = m_seed; 1575 | FN_DECIMAL sum = SingleCubic(seed, x, y, z); 1576 | FN_DECIMAL amp = 1; 1577 | int i = 0; 1578 | 1579 | while (++i < m_octaves) 1580 | { 1581 | x *= m_lacunarity; 1582 | y *= m_lacunarity; 1583 | z *= m_lacunarity; 1584 | 1585 | amp *= m_gain; 1586 | sum += SingleCubic(++seed, x, y, z) * amp; 1587 | } 1588 | 1589 | return sum * m_fractalBounding; 1590 | } 1591 | 1592 | private FN_DECIMAL SingleCubicFractalBillow(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1593 | { 1594 | int seed = m_seed; 1595 | FN_DECIMAL sum = Math.Abs(SingleCubic(seed, x, y, z)) * 2 - 1; 1596 | FN_DECIMAL amp = 1; 1597 | int i = 0; 1598 | 1599 | while (++i < m_octaves) 1600 | { 1601 | x *= m_lacunarity; 1602 | y *= m_lacunarity; 1603 | z *= m_lacunarity; 1604 | 1605 | amp *= m_gain; 1606 | sum += (Math.Abs(SingleCubic(++seed, x, y, z)) * 2 - 1) * amp; 1607 | } 1608 | 1609 | return sum * m_fractalBounding; 1610 | } 1611 | 1612 | private FN_DECIMAL SingleCubicFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1613 | { 1614 | int seed = m_seed; 1615 | FN_DECIMAL sum = 1 - Math.Abs(SingleCubic(seed, x, y, z)); 1616 | FN_DECIMAL amp = 1; 1617 | int i = 0; 1618 | 1619 | while (++i < m_octaves) 1620 | { 1621 | x *= m_lacunarity; 1622 | y *= m_lacunarity; 1623 | z *= m_lacunarity; 1624 | 1625 | amp *= m_gain; 1626 | sum -= (1 - Math.Abs(SingleCubic(++seed, x, y, z))) * amp; 1627 | } 1628 | 1629 | return sum; 1630 | } 1631 | 1632 | public FN_DECIMAL GetCubic(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1633 | { 1634 | return SingleCubic(m_seed, x * m_frequency, y * m_frequency, z * m_frequency); 1635 | } 1636 | 1637 | private const FN_DECIMAL CUBIC_3D_BOUNDING = 1 / (FN_DECIMAL)(1.5 * 1.5 * 1.5); 1638 | 1639 | private FN_DECIMAL SingleCubic(int seed, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1640 | { 1641 | int x1 = FastFloor(x); 1642 | int y1 = FastFloor(y); 1643 | int z1 = FastFloor(z); 1644 | 1645 | int x0 = x1 - 1; 1646 | int y0 = y1 - 1; 1647 | int z0 = z1 - 1; 1648 | int x2 = x1 + 1; 1649 | int y2 = y1 + 1; 1650 | int z2 = z1 + 1; 1651 | int x3 = x1 + 2; 1652 | int y3 = y1 + 2; 1653 | int z3 = z1 + 2; 1654 | 1655 | FN_DECIMAL xs = x - (FN_DECIMAL)x1; 1656 | FN_DECIMAL ys = y - (FN_DECIMAL)y1; 1657 | FN_DECIMAL zs = z - (FN_DECIMAL)z1; 1658 | 1659 | return CubicLerp( 1660 | CubicLerp( 1661 | CubicLerp(ValCoord3D(seed, x0, y0, z0), ValCoord3D(seed, x1, y0, z0), ValCoord3D(seed, x2, y0, z0), ValCoord3D(seed, x3, y0, z0), xs), 1662 | CubicLerp(ValCoord3D(seed, x0, y1, z0), ValCoord3D(seed, x1, y1, z0), ValCoord3D(seed, x2, y1, z0), ValCoord3D(seed, x3, y1, z0), xs), 1663 | CubicLerp(ValCoord3D(seed, x0, y2, z0), ValCoord3D(seed, x1, y2, z0), ValCoord3D(seed, x2, y2, z0), ValCoord3D(seed, x3, y2, z0), xs), 1664 | CubicLerp(ValCoord3D(seed, x0, y3, z0), ValCoord3D(seed, x1, y3, z0), ValCoord3D(seed, x2, y3, z0), ValCoord3D(seed, x3, y3, z0), xs), 1665 | ys), 1666 | CubicLerp( 1667 | CubicLerp(ValCoord3D(seed, x0, y0, z1), ValCoord3D(seed, x1, y0, z1), ValCoord3D(seed, x2, y0, z1), ValCoord3D(seed, x3, y0, z1), xs), 1668 | CubicLerp(ValCoord3D(seed, x0, y1, z1), ValCoord3D(seed, x1, y1, z1), ValCoord3D(seed, x2, y1, z1), ValCoord3D(seed, x3, y1, z1), xs), 1669 | CubicLerp(ValCoord3D(seed, x0, y2, z1), ValCoord3D(seed, x1, y2, z1), ValCoord3D(seed, x2, y2, z1), ValCoord3D(seed, x3, y2, z1), xs), 1670 | CubicLerp(ValCoord3D(seed, x0, y3, z1), ValCoord3D(seed, x1, y3, z1), ValCoord3D(seed, x2, y3, z1), ValCoord3D(seed, x3, y3, z1), xs), 1671 | ys), 1672 | CubicLerp( 1673 | CubicLerp(ValCoord3D(seed, x0, y0, z2), ValCoord3D(seed, x1, y0, z2), ValCoord3D(seed, x2, y0, z2), ValCoord3D(seed, x3, y0, z2), xs), 1674 | CubicLerp(ValCoord3D(seed, x0, y1, z2), ValCoord3D(seed, x1, y1, z2), ValCoord3D(seed, x2, y1, z2), ValCoord3D(seed, x3, y1, z2), xs), 1675 | CubicLerp(ValCoord3D(seed, x0, y2, z2), ValCoord3D(seed, x1, y2, z2), ValCoord3D(seed, x2, y2, z2), ValCoord3D(seed, x3, y2, z2), xs), 1676 | CubicLerp(ValCoord3D(seed, x0, y3, z2), ValCoord3D(seed, x1, y3, z2), ValCoord3D(seed, x2, y3, z2), ValCoord3D(seed, x3, y3, z2), xs), 1677 | ys), 1678 | CubicLerp( 1679 | CubicLerp(ValCoord3D(seed, x0, y0, z3), ValCoord3D(seed, x1, y0, z3), ValCoord3D(seed, x2, y0, z3), ValCoord3D(seed, x3, y0, z3), xs), 1680 | CubicLerp(ValCoord3D(seed, x0, y1, z3), ValCoord3D(seed, x1, y1, z3), ValCoord3D(seed, x2, y1, z3), ValCoord3D(seed, x3, y1, z3), xs), 1681 | CubicLerp(ValCoord3D(seed, x0, y2, z3), ValCoord3D(seed, x1, y2, z3), ValCoord3D(seed, x2, y2, z3), ValCoord3D(seed, x3, y2, z3), xs), 1682 | CubicLerp(ValCoord3D(seed, x0, y3, z3), ValCoord3D(seed, x1, y3, z3), ValCoord3D(seed, x2, y3, z3), ValCoord3D(seed, x3, y3, z3), xs), 1683 | ys), 1684 | zs) * CUBIC_3D_BOUNDING; 1685 | } 1686 | 1687 | 1688 | public FN_DECIMAL GetCubicFractal(FN_DECIMAL x, FN_DECIMAL y) 1689 | { 1690 | x *= m_frequency; 1691 | y *= m_frequency; 1692 | 1693 | switch (m_fractalType) 1694 | { 1695 | case FractalType.FBM: 1696 | return SingleCubicFractalFBM(x, y); 1697 | case FractalType.Billow: 1698 | return SingleCubicFractalBillow(x, y); 1699 | case FractalType.RigidMulti: 1700 | return SingleCubicFractalRigidMulti(x, y); 1701 | default: 1702 | return 0; 1703 | } 1704 | } 1705 | 1706 | private FN_DECIMAL SingleCubicFractalFBM(FN_DECIMAL x, FN_DECIMAL y) 1707 | { 1708 | int seed = m_seed; 1709 | FN_DECIMAL sum = SingleCubic(seed, x, y); 1710 | FN_DECIMAL amp = 1; 1711 | int i = 0; 1712 | 1713 | while (++i < m_octaves) 1714 | { 1715 | x *= m_lacunarity; 1716 | y *= m_lacunarity; 1717 | 1718 | amp *= m_gain; 1719 | sum += SingleCubic(++seed, x, y) * amp; 1720 | } 1721 | 1722 | return sum * m_fractalBounding; 1723 | } 1724 | 1725 | private FN_DECIMAL SingleCubicFractalBillow(FN_DECIMAL x, FN_DECIMAL y) 1726 | { 1727 | int seed = m_seed; 1728 | FN_DECIMAL sum = Math.Abs(SingleCubic(seed, x, y)) * 2 - 1; 1729 | FN_DECIMAL amp = 1; 1730 | int i = 0; 1731 | 1732 | while (++i < m_octaves) 1733 | { 1734 | x *= m_lacunarity; 1735 | y *= m_lacunarity; 1736 | 1737 | amp *= m_gain; 1738 | sum += (Math.Abs(SingleCubic(++seed, x, y)) * 2 - 1) * amp; 1739 | } 1740 | 1741 | return sum * m_fractalBounding; 1742 | } 1743 | 1744 | private FN_DECIMAL SingleCubicFractalRigidMulti(FN_DECIMAL x, FN_DECIMAL y) 1745 | { 1746 | int seed = m_seed; 1747 | FN_DECIMAL sum = 1 - Math.Abs(SingleCubic(seed, x, y)); 1748 | FN_DECIMAL amp = 1; 1749 | int i = 0; 1750 | 1751 | while (++i < m_octaves) 1752 | { 1753 | x *= m_lacunarity; 1754 | y *= m_lacunarity; 1755 | 1756 | amp *= m_gain; 1757 | sum -= (1 - Math.Abs(SingleCubic(++seed, x, y))) * amp; 1758 | } 1759 | 1760 | return sum; 1761 | } 1762 | 1763 | public FN_DECIMAL GetCubic(FN_DECIMAL x, FN_DECIMAL y) 1764 | { 1765 | x *= m_frequency; 1766 | y *= m_frequency; 1767 | 1768 | return SingleCubic(0, x, y); 1769 | } 1770 | 1771 | private const FN_DECIMAL CUBIC_2D_BOUNDING = 1 / (FN_DECIMAL)(1.5 * 1.5); 1772 | 1773 | private FN_DECIMAL SingleCubic(int seed, FN_DECIMAL x, FN_DECIMAL y) 1774 | { 1775 | int x1 = FastFloor(x); 1776 | int y1 = FastFloor(y); 1777 | 1778 | int x0 = x1 - 1; 1779 | int y0 = y1 - 1; 1780 | int x2 = x1 + 1; 1781 | int y2 = y1 + 1; 1782 | int x3 = x1 + 2; 1783 | int y3 = y1 + 2; 1784 | 1785 | FN_DECIMAL xs = x - (FN_DECIMAL)x1; 1786 | FN_DECIMAL ys = y - (FN_DECIMAL)y1; 1787 | 1788 | return CubicLerp( 1789 | CubicLerp(ValCoord2D(seed, x0, y0), ValCoord2D(seed, x1, y0), ValCoord2D(seed, x2, y0), ValCoord2D(seed, x3, y0), 1790 | xs), 1791 | CubicLerp(ValCoord2D(seed, x0, y1), ValCoord2D(seed, x1, y1), ValCoord2D(seed, x2, y1), ValCoord2D(seed, x3, y1), 1792 | xs), 1793 | CubicLerp(ValCoord2D(seed, x0, y2), ValCoord2D(seed, x1, y2), ValCoord2D(seed, x2, y2), ValCoord2D(seed, x3, y2), 1794 | xs), 1795 | CubicLerp(ValCoord2D(seed, x0, y3), ValCoord2D(seed, x1, y3), ValCoord2D(seed, x2, y3), ValCoord2D(seed, x3, y3), 1796 | xs), 1797 | ys) * CUBIC_2D_BOUNDING; 1798 | } 1799 | 1800 | // Cellular Noise 1801 | public FN_DECIMAL GetCellular(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1802 | { 1803 | x *= m_frequency; 1804 | y *= m_frequency; 1805 | z *= m_frequency; 1806 | 1807 | switch (m_cellularReturnType) 1808 | { 1809 | case CellularReturnType.CellValue: 1810 | case CellularReturnType.NoiseLookup: 1811 | case CellularReturnType.Distance: 1812 | return SingleCellular(x, y, z); 1813 | default: 1814 | return SingleCellular2Edge(x, y, z); 1815 | } 1816 | } 1817 | 1818 | private FN_DECIMAL SingleCellular(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1819 | { 1820 | int xr = FastRound(x); 1821 | int yr = FastRound(y); 1822 | int zr = FastRound(z); 1823 | 1824 | FN_DECIMAL distance = 999999; 1825 | int xc = 0, yc = 0, zc = 0; 1826 | 1827 | switch (m_cellularDistanceFunction) 1828 | { 1829 | case CellularDistanceFunction.Euclidean: 1830 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1831 | { 1832 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1833 | { 1834 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1835 | { 1836 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1837 | 1838 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1839 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1840 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1841 | 1842 | FN_DECIMAL newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; 1843 | 1844 | if (newDistance < distance) 1845 | { 1846 | distance = newDistance; 1847 | xc = xi; 1848 | yc = yi; 1849 | zc = zi; 1850 | } 1851 | } 1852 | } 1853 | } 1854 | break; 1855 | case CellularDistanceFunction.Manhattan: 1856 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1857 | { 1858 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1859 | { 1860 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1861 | { 1862 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1863 | 1864 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1865 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1866 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1867 | 1868 | FN_DECIMAL newDistance = Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ); 1869 | 1870 | if (newDistance < distance) 1871 | { 1872 | distance = newDistance; 1873 | xc = xi; 1874 | yc = yi; 1875 | zc = zi; 1876 | } 1877 | } 1878 | } 1879 | } 1880 | break; 1881 | case CellularDistanceFunction.Natural: 1882 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1883 | { 1884 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1885 | { 1886 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1887 | { 1888 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1889 | 1890 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1891 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1892 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1893 | 1894 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ); 1895 | 1896 | if (newDistance < distance) 1897 | { 1898 | distance = newDistance; 1899 | xc = xi; 1900 | yc = yi; 1901 | zc = zi; 1902 | } 1903 | } 1904 | } 1905 | } 1906 | break; 1907 | } 1908 | 1909 | switch (m_cellularReturnType) 1910 | { 1911 | case CellularReturnType.CellValue: 1912 | return ValCoord3D(m_seed, xc, yc, zc); 1913 | 1914 | case CellularReturnType.NoiseLookup: 1915 | Float3 vec = CELL_3D[Hash3D(m_seed, xc, yc, zc) & 255]; 1916 | return m_cellularNoiseLookup.GetNoise(xc + vec.x * m_cellularJitter, yc + vec.y * m_cellularJitter, zc + vec.z * m_cellularJitter); 1917 | 1918 | case CellularReturnType.Distance: 1919 | return distance; 1920 | default: 1921 | return 0; 1922 | } 1923 | } 1924 | 1925 | private FN_DECIMAL SingleCellular2Edge(FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z) 1926 | { 1927 | int xr = FastRound(x); 1928 | int yr = FastRound(y); 1929 | int zr = FastRound(z); 1930 | 1931 | FN_DECIMAL[] distance = { 999999, 999999, 999999, 999999 }; 1932 | 1933 | switch (m_cellularDistanceFunction) 1934 | { 1935 | case CellularDistanceFunction.Euclidean: 1936 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1937 | { 1938 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1939 | { 1940 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1941 | { 1942 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1943 | 1944 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1945 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1946 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1947 | 1948 | FN_DECIMAL newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; 1949 | 1950 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 1951 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 1952 | distance[0] = Math.Min(distance[0], newDistance); 1953 | } 1954 | } 1955 | } 1956 | break; 1957 | case CellularDistanceFunction.Manhattan: 1958 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1959 | { 1960 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1961 | { 1962 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1963 | { 1964 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1965 | 1966 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1967 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1968 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1969 | 1970 | FN_DECIMAL newDistance = Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ); 1971 | 1972 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 1973 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 1974 | distance[0] = Math.Min(distance[0], newDistance); 1975 | } 1976 | } 1977 | } 1978 | break; 1979 | case CellularDistanceFunction.Natural: 1980 | for (int xi = xr - 1; xi <= xr + 1; xi++) 1981 | { 1982 | for (int yi = yr - 1; yi <= yr + 1; yi++) 1983 | { 1984 | for (int zi = zr - 1; zi <= zr + 1; zi++) 1985 | { 1986 | Float3 vec = CELL_3D[Hash3D(m_seed, xi, yi, zi) & 255]; 1987 | 1988 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 1989 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 1990 | FN_DECIMAL vecZ = zi - z + vec.z * m_cellularJitter; 1991 | 1992 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY) + Math.Abs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ); 1993 | 1994 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 1995 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 1996 | distance[0] = Math.Min(distance[0], newDistance); 1997 | } 1998 | } 1999 | } 2000 | break; 2001 | default: 2002 | break; 2003 | } 2004 | 2005 | switch (m_cellularReturnType) 2006 | { 2007 | case CellularReturnType.Distance2: 2008 | return distance[m_cellularDistanceIndex1]; 2009 | case CellularReturnType.Distance2Add: 2010 | return distance[m_cellularDistanceIndex1] + distance[m_cellularDistanceIndex0]; 2011 | case CellularReturnType.Distance2Sub: 2012 | return distance[m_cellularDistanceIndex1] - distance[m_cellularDistanceIndex0]; 2013 | case CellularReturnType.Distance2Mul: 2014 | return distance[m_cellularDistanceIndex1] * distance[m_cellularDistanceIndex0]; 2015 | case CellularReturnType.Distance2Div: 2016 | return distance[m_cellularDistanceIndex0] / distance[m_cellularDistanceIndex1]; 2017 | default: 2018 | return 0; 2019 | } 2020 | } 2021 | 2022 | public FN_DECIMAL GetCellular(FN_DECIMAL x, FN_DECIMAL y) 2023 | { 2024 | x *= m_frequency; 2025 | y *= m_frequency; 2026 | 2027 | switch (m_cellularReturnType) 2028 | { 2029 | case CellularReturnType.CellValue: 2030 | case CellularReturnType.NoiseLookup: 2031 | case CellularReturnType.Distance: 2032 | return SingleCellular(x, y); 2033 | default: 2034 | return SingleCellular2Edge(x, y); 2035 | } 2036 | } 2037 | 2038 | private FN_DECIMAL SingleCellular(FN_DECIMAL x, FN_DECIMAL y) 2039 | { 2040 | int xr = FastRound(x); 2041 | int yr = FastRound(y); 2042 | 2043 | FN_DECIMAL distance = 999999; 2044 | int xc = 0, yc = 0; 2045 | 2046 | switch (m_cellularDistanceFunction) 2047 | { 2048 | default: 2049 | case CellularDistanceFunction.Euclidean: 2050 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2051 | { 2052 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2053 | { 2054 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2055 | 2056 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2057 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2058 | 2059 | FN_DECIMAL newDistance = vecX * vecX + vecY * vecY; 2060 | 2061 | if (newDistance < distance) 2062 | { 2063 | distance = newDistance; 2064 | xc = xi; 2065 | yc = yi; 2066 | } 2067 | } 2068 | } 2069 | break; 2070 | case CellularDistanceFunction.Manhattan: 2071 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2072 | { 2073 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2074 | { 2075 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2076 | 2077 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2078 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2079 | 2080 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY)); 2081 | 2082 | if (newDistance < distance) 2083 | { 2084 | distance = newDistance; 2085 | xc = xi; 2086 | yc = yi; 2087 | } 2088 | } 2089 | } 2090 | break; 2091 | case CellularDistanceFunction.Natural: 2092 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2093 | { 2094 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2095 | { 2096 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2097 | 2098 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2099 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2100 | 2101 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY)) + (vecX * vecX + vecY * vecY); 2102 | 2103 | if (newDistance < distance) 2104 | { 2105 | distance = newDistance; 2106 | xc = xi; 2107 | yc = yi; 2108 | } 2109 | } 2110 | } 2111 | break; 2112 | } 2113 | 2114 | switch (m_cellularReturnType) 2115 | { 2116 | case CellularReturnType.CellValue: 2117 | return ValCoord2D(m_seed, xc, yc); 2118 | 2119 | case CellularReturnType.NoiseLookup: 2120 | Float2 vec = CELL_2D[Hash2D(m_seed, xc, yc) & 255]; 2121 | return m_cellularNoiseLookup.GetNoise(xc + vec.x * m_cellularJitter, yc + vec.y * m_cellularJitter); 2122 | 2123 | case CellularReturnType.Distance: 2124 | return distance; 2125 | default: 2126 | return 0; 2127 | } 2128 | } 2129 | 2130 | private FN_DECIMAL SingleCellular2Edge(FN_DECIMAL x, FN_DECIMAL y) 2131 | { 2132 | int xr = FastRound(x); 2133 | int yr = FastRound(y); 2134 | 2135 | FN_DECIMAL[] distance = { 999999, 999999, 999999, 999999 }; 2136 | 2137 | switch (m_cellularDistanceFunction) 2138 | { 2139 | default: 2140 | case CellularDistanceFunction.Euclidean: 2141 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2142 | { 2143 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2144 | { 2145 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2146 | 2147 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2148 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2149 | 2150 | FN_DECIMAL newDistance = vecX * vecX + vecY * vecY; 2151 | 2152 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 2153 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 2154 | distance[0] = Math.Min(distance[0], newDistance); 2155 | } 2156 | } 2157 | break; 2158 | case CellularDistanceFunction.Manhattan: 2159 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2160 | { 2161 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2162 | { 2163 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2164 | 2165 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2166 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2167 | 2168 | FN_DECIMAL newDistance = Math.Abs(vecX) + Math.Abs(vecY); 2169 | 2170 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 2171 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 2172 | distance[0] = Math.Min(distance[0], newDistance); 2173 | } 2174 | } 2175 | break; 2176 | case CellularDistanceFunction.Natural: 2177 | for (int xi = xr - 1; xi <= xr + 1; xi++) 2178 | { 2179 | for (int yi = yr - 1; yi <= yr + 1; yi++) 2180 | { 2181 | Float2 vec = CELL_2D[Hash2D(m_seed, xi, yi) & 255]; 2182 | 2183 | FN_DECIMAL vecX = xi - x + vec.x * m_cellularJitter; 2184 | FN_DECIMAL vecY = yi - y + vec.y * m_cellularJitter; 2185 | 2186 | FN_DECIMAL newDistance = (Math.Abs(vecX) + Math.Abs(vecY)) + (vecX * vecX + vecY * vecY); 2187 | 2188 | for (int i = m_cellularDistanceIndex1; i > 0; i--) 2189 | distance[i] = Math.Max(Math.Min(distance[i], newDistance), distance[i - 1]); 2190 | distance[0] = Math.Min(distance[0], newDistance); 2191 | } 2192 | } 2193 | break; 2194 | } 2195 | 2196 | switch (m_cellularReturnType) 2197 | { 2198 | case CellularReturnType.Distance2: 2199 | return distance[m_cellularDistanceIndex1]; 2200 | case CellularReturnType.Distance2Add: 2201 | return distance[m_cellularDistanceIndex1] + distance[m_cellularDistanceIndex0]; 2202 | case CellularReturnType.Distance2Sub: 2203 | return distance[m_cellularDistanceIndex1] - distance[m_cellularDistanceIndex0]; 2204 | case CellularReturnType.Distance2Mul: 2205 | return distance[m_cellularDistanceIndex1] * distance[m_cellularDistanceIndex0]; 2206 | case CellularReturnType.Distance2Div: 2207 | return distance[m_cellularDistanceIndex0] / distance[m_cellularDistanceIndex1]; 2208 | default: 2209 | return 0; 2210 | } 2211 | } 2212 | 2213 | public void GradientPerturb(ref FN_DECIMAL x, ref FN_DECIMAL y, ref FN_DECIMAL z) 2214 | { 2215 | SingleGradientPerturb(m_seed, m_gradientPerturbAmp, m_frequency, ref x, ref y, ref z); 2216 | } 2217 | 2218 | public void GradientPerturbFractal(ref FN_DECIMAL x, ref FN_DECIMAL y, ref FN_DECIMAL z) 2219 | { 2220 | int seed = m_seed; 2221 | FN_DECIMAL amp = m_gradientPerturbAmp * m_fractalBounding; 2222 | FN_DECIMAL freq = m_frequency; 2223 | 2224 | SingleGradientPerturb(seed, amp, m_frequency, ref x, ref y, ref z); 2225 | 2226 | for (int i = 1; i < m_octaves; i++) 2227 | { 2228 | freq *= m_lacunarity; 2229 | amp *= m_gain; 2230 | SingleGradientPerturb(++seed, amp, freq, ref x, ref y, ref z); 2231 | } 2232 | } 2233 | 2234 | private void SingleGradientPerturb(int seed, FN_DECIMAL perturbAmp, FN_DECIMAL frequency, ref FN_DECIMAL x, ref FN_DECIMAL y, ref FN_DECIMAL z) 2235 | { 2236 | FN_DECIMAL xf = x * frequency; 2237 | FN_DECIMAL yf = y * frequency; 2238 | FN_DECIMAL zf = z * frequency; 2239 | 2240 | int x0 = FastFloor(xf); 2241 | int y0 = FastFloor(yf); 2242 | int z0 = FastFloor(zf); 2243 | int x1 = x0 + 1; 2244 | int y1 = y0 + 1; 2245 | int z1 = z0 + 1; 2246 | 2247 | FN_DECIMAL xs, ys, zs; 2248 | switch (m_interp) 2249 | { 2250 | default: 2251 | case Interp.Linear: 2252 | xs = xf - x0; 2253 | ys = yf - y0; 2254 | zs = zf - z0; 2255 | break; 2256 | case Interp.Hermite: 2257 | xs = InterpHermiteFunc(xf - x0); 2258 | ys = InterpHermiteFunc(yf - y0); 2259 | zs = InterpHermiteFunc(zf - z0); 2260 | break; 2261 | case Interp.Quintic: 2262 | xs = InterpQuinticFunc(xf - x0); 2263 | ys = InterpQuinticFunc(yf - y0); 2264 | zs = InterpQuinticFunc(zf - z0); 2265 | break; 2266 | } 2267 | 2268 | Float3 vec0 = CELL_3D[Hash3D(seed, x0, y0, z0) & 255]; 2269 | Float3 vec1 = CELL_3D[Hash3D(seed, x1, y0, z0) & 255]; 2270 | 2271 | FN_DECIMAL lx0x = Lerp(vec0.x, vec1.x, xs); 2272 | FN_DECIMAL ly0x = Lerp(vec0.y, vec1.y, xs); 2273 | FN_DECIMAL lz0x = Lerp(vec0.z, vec1.z, xs); 2274 | 2275 | vec0 = CELL_3D[Hash3D(seed, x0, y1, z0) & 255]; 2276 | vec1 = CELL_3D[Hash3D(seed, x1, y1, z0) & 255]; 2277 | 2278 | FN_DECIMAL lx1x = Lerp(vec0.x, vec1.x, xs); 2279 | FN_DECIMAL ly1x = Lerp(vec0.y, vec1.y, xs); 2280 | FN_DECIMAL lz1x = Lerp(vec0.z, vec1.z, xs); 2281 | 2282 | FN_DECIMAL lx0y = Lerp(lx0x, lx1x, ys); 2283 | FN_DECIMAL ly0y = Lerp(ly0x, ly1x, ys); 2284 | FN_DECIMAL lz0y = Lerp(lz0x, lz1x, ys); 2285 | 2286 | vec0 = CELL_3D[Hash3D(seed, x0, y0, z1) & 255]; 2287 | vec1 = CELL_3D[Hash3D(seed, x1, y0, z1) & 255]; 2288 | 2289 | lx0x = Lerp(vec0.x, vec1.x, xs); 2290 | ly0x = Lerp(vec0.y, vec1.y, xs); 2291 | lz0x = Lerp(vec0.z, vec1.z, xs); 2292 | 2293 | vec0 = CELL_3D[Hash3D(seed, x0, y1, z1) & 255]; 2294 | vec1 = CELL_3D[Hash3D(seed, x1, y1, z1) & 255]; 2295 | 2296 | lx1x = Lerp(vec0.x, vec1.x, xs); 2297 | ly1x = Lerp(vec0.y, vec1.y, xs); 2298 | lz1x = Lerp(vec0.z, vec1.z, xs); 2299 | 2300 | x += Lerp(lx0y, Lerp(lx0x, lx1x, ys), zs) * perturbAmp; 2301 | y += Lerp(ly0y, Lerp(ly0x, ly1x, ys), zs) * perturbAmp; 2302 | z += Lerp(lz0y, Lerp(lz0x, lz1x, ys), zs) * perturbAmp; 2303 | } 2304 | 2305 | public void GradientPerturb(ref FN_DECIMAL x, ref FN_DECIMAL y) 2306 | { 2307 | SingleGradientPerturb(m_seed, m_gradientPerturbAmp, m_frequency, ref x, ref y); 2308 | } 2309 | 2310 | public void GradientPerturbFractal(ref FN_DECIMAL x, ref FN_DECIMAL y) 2311 | { 2312 | int seed = m_seed; 2313 | FN_DECIMAL amp = m_gradientPerturbAmp * m_fractalBounding; 2314 | FN_DECIMAL freq = m_frequency; 2315 | 2316 | SingleGradientPerturb(seed, amp, m_frequency, ref x, ref y); 2317 | 2318 | for (int i = 1; i < m_octaves; i++) 2319 | { 2320 | freq *= m_lacunarity; 2321 | amp *= m_gain; 2322 | SingleGradientPerturb(++seed, amp, freq, ref x, ref y); 2323 | } 2324 | } 2325 | 2326 | private void SingleGradientPerturb(int seed, FN_DECIMAL perturbAmp, FN_DECIMAL frequency, ref FN_DECIMAL x, ref FN_DECIMAL y) 2327 | { 2328 | FN_DECIMAL xf = x * frequency; 2329 | FN_DECIMAL yf = y * frequency; 2330 | 2331 | int x0 = FastFloor(xf); 2332 | int y0 = FastFloor(yf); 2333 | int x1 = x0 + 1; 2334 | int y1 = y0 + 1; 2335 | 2336 | FN_DECIMAL xs, ys; 2337 | switch (m_interp) 2338 | { 2339 | default: 2340 | case Interp.Linear: 2341 | xs = xf - x0; 2342 | ys = yf - y0; 2343 | break; 2344 | case Interp.Hermite: 2345 | xs = InterpHermiteFunc(xf - x0); 2346 | ys = InterpHermiteFunc(yf - y0); 2347 | break; 2348 | case Interp.Quintic: 2349 | xs = InterpQuinticFunc(xf - x0); 2350 | ys = InterpQuinticFunc(yf - y0); 2351 | break; 2352 | } 2353 | 2354 | Float2 vec0 = CELL_2D[Hash2D(seed, x0, y0) & 255]; 2355 | Float2 vec1 = CELL_2D[Hash2D(seed, x1, y0) & 255]; 2356 | 2357 | FN_DECIMAL lx0x = Lerp(vec0.x, vec1.x, xs); 2358 | FN_DECIMAL ly0x = Lerp(vec0.y, vec1.y, xs); 2359 | 2360 | vec0 = CELL_2D[Hash2D(seed, x0, y1) & 255]; 2361 | vec1 = CELL_2D[Hash2D(seed, x1, y1) & 255]; 2362 | 2363 | FN_DECIMAL lx1x = Lerp(vec0.x, vec1.x, xs); 2364 | FN_DECIMAL ly1x = Lerp(vec0.y, vec1.y, xs); 2365 | 2366 | x += Lerp(lx0x, lx1x, ys) * perturbAmp; 2367 | y += Lerp(ly0x, ly1x, ys) * perturbAmp; 2368 | } 2369 | 2370 | } 2371 | --------------------------------------------------------------------------------