├── .gitignore ├── .prettierrc ├── README.md ├── index.html ├── package.json ├── pnpm-lock.yaml ├── public └── vite.svg ├── screenshot.jpg ├── src ├── App.css ├── App.tsx ├── colors │ ├── useDisplay.ts │ ├── useHeightMap.ts │ └── useNaturalColor.ts ├── components │ ├── GUI.tsx │ ├── Gizmo.tsx │ ├── Lights.tsx │ ├── Terrain.tsx │ └── TerrainStats.tsx ├── geometry │ ├── useFbmNoise.ts │ ├── useProceduralTerrain.ts │ └── useSquareSurface.ts ├── lib │ └── three-noise.module.ts ├── main.tsx ├── state │ └── useSettings.ts └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | stats.html 15 | 16 | # Editor directories and files 17 | .vscode/* 18 | !.vscode/extensions.json 19 | .idea 20 | .DS_Store 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 90, 3 | "trailingComma": "none" 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Procedural 3D Terrain with react-three-fiber 2 | 3 | Inspired by a Codesandbox by Faraz Shaikh. 4 | 5 |

6 | 7 | Screenshot of the procedural terrain editor 8 | 9 |

10 | 11 |

12 | 13 | Edit 3d-terrain-r3f 14 | 15 |

16 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 3D Terrain 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "3d-terrain-r3f", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "build": "tsc && vite build", 8 | "dev": "vite", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@react-three/drei": "9.29.1", 13 | "@react-three/fiber": "8.7.2", 14 | "immer": "9.0.15", 15 | "leva": "0.9.31", 16 | "react": "18.2.0", 17 | "react-dom": "18.2.0", 18 | "three": "0.144.0", 19 | "zustand": "4.1.1" 20 | }, 21 | "devDependencies": { 22 | "@types/react": "18.0.17", 23 | "@types/react-dom": "18.0.6", 24 | "@types/three": "0.144.0", 25 | "@vitejs/plugin-react": "2.1.0", 26 | "rollup-plugin-visualizer": "5.8.1", 27 | "typescript": "4.6.4", 28 | "vite": "3.1.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.4 2 | 3 | specifiers: 4 | '@react-three/drei': 9.29.1 5 | '@react-three/fiber': 8.7.2 6 | '@types/react': 18.0.17 7 | '@types/react-dom': 18.0.6 8 | '@types/three': 0.144.0 9 | '@vitejs/plugin-react': 2.1.0 10 | immer: 9.0.15 11 | leva: 0.9.31 12 | react: 18.2.0 13 | react-dom: 18.2.0 14 | rollup-plugin-visualizer: 5.8.1 15 | three: 0.144.0 16 | typescript: 4.6.4 17 | vite: 3.1.0 18 | zustand: 4.1.1 19 | 20 | dependencies: 21 | '@react-three/drei': 9.29.1_gjrj76muidflkn6okfckfwmak4 22 | '@react-three/fiber': 8.7.2_ww22p6cticflcq7fk2rysgxj34 23 | immer: 9.0.15 24 | leva: 0.9.31_biqbaboplfbrettd7655fr4n2y 25 | react: 18.2.0 26 | react-dom: 18.2.0_react@18.2.0 27 | three: 0.144.0 28 | zustand: 4.1.1_immer@9.0.15+react@18.2.0 29 | 30 | devDependencies: 31 | '@types/react': 18.0.17 32 | '@types/react-dom': 18.0.6 33 | '@types/three': 0.144.0 34 | '@vitejs/plugin-react': 2.1.0_vite@3.1.0 35 | rollup-plugin-visualizer: 5.8.1 36 | typescript: 4.6.4 37 | vite: 3.1.0 38 | 39 | packages: 40 | 41 | /@ampproject/remapping/2.2.0: 42 | resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} 43 | engines: {node: '>=6.0.0'} 44 | dependencies: 45 | '@jridgewell/gen-mapping': 0.1.1 46 | '@jridgewell/trace-mapping': 0.3.15 47 | dev: true 48 | 49 | /@babel/code-frame/7.18.6: 50 | resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} 51 | engines: {node: '>=6.9.0'} 52 | dependencies: 53 | '@babel/highlight': 7.18.6 54 | dev: true 55 | 56 | /@babel/compat-data/7.19.0: 57 | resolution: {integrity: sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw==} 58 | engines: {node: '>=6.9.0'} 59 | dev: true 60 | 61 | /@babel/core/7.19.0: 62 | resolution: {integrity: sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==} 63 | engines: {node: '>=6.9.0'} 64 | dependencies: 65 | '@ampproject/remapping': 2.2.0 66 | '@babel/code-frame': 7.18.6 67 | '@babel/generator': 7.19.0 68 | '@babel/helper-compilation-targets': 7.19.0_@babel+core@7.19.0 69 | '@babel/helper-module-transforms': 7.19.0 70 | '@babel/helpers': 7.19.0 71 | '@babel/parser': 7.19.0 72 | '@babel/template': 7.18.10 73 | '@babel/traverse': 7.19.0 74 | '@babel/types': 7.19.0 75 | convert-source-map: 1.8.0 76 | debug: 4.3.4 77 | gensync: 1.0.0-beta.2 78 | json5: 2.2.1 79 | semver: 6.3.0 80 | transitivePeerDependencies: 81 | - supports-color 82 | dev: true 83 | 84 | /@babel/generator/7.19.0: 85 | resolution: {integrity: sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==} 86 | engines: {node: '>=6.9.0'} 87 | dependencies: 88 | '@babel/types': 7.19.0 89 | '@jridgewell/gen-mapping': 0.3.2 90 | jsesc: 2.5.2 91 | dev: true 92 | 93 | /@babel/helper-annotate-as-pure/7.18.6: 94 | resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} 95 | engines: {node: '>=6.9.0'} 96 | dependencies: 97 | '@babel/types': 7.19.0 98 | dev: true 99 | 100 | /@babel/helper-compilation-targets/7.19.0_@babel+core@7.19.0: 101 | resolution: {integrity: sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA==} 102 | engines: {node: '>=6.9.0'} 103 | peerDependencies: 104 | '@babel/core': ^7.0.0 105 | dependencies: 106 | '@babel/compat-data': 7.19.0 107 | '@babel/core': 7.19.0 108 | '@babel/helper-validator-option': 7.18.6 109 | browserslist: 4.21.3 110 | semver: 6.3.0 111 | dev: true 112 | 113 | /@babel/helper-environment-visitor/7.18.9: 114 | resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} 115 | engines: {node: '>=6.9.0'} 116 | dev: true 117 | 118 | /@babel/helper-function-name/7.19.0: 119 | resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} 120 | engines: {node: '>=6.9.0'} 121 | dependencies: 122 | '@babel/template': 7.18.10 123 | '@babel/types': 7.19.0 124 | dev: true 125 | 126 | /@babel/helper-hoist-variables/7.18.6: 127 | resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} 128 | engines: {node: '>=6.9.0'} 129 | dependencies: 130 | '@babel/types': 7.19.0 131 | dev: true 132 | 133 | /@babel/helper-module-imports/7.18.6: 134 | resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} 135 | engines: {node: '>=6.9.0'} 136 | dependencies: 137 | '@babel/types': 7.19.0 138 | dev: true 139 | 140 | /@babel/helper-module-transforms/7.19.0: 141 | resolution: {integrity: sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==} 142 | engines: {node: '>=6.9.0'} 143 | dependencies: 144 | '@babel/helper-environment-visitor': 7.18.9 145 | '@babel/helper-module-imports': 7.18.6 146 | '@babel/helper-simple-access': 7.18.6 147 | '@babel/helper-split-export-declaration': 7.18.6 148 | '@babel/helper-validator-identifier': 7.18.6 149 | '@babel/template': 7.18.10 150 | '@babel/traverse': 7.19.0 151 | '@babel/types': 7.19.0 152 | transitivePeerDependencies: 153 | - supports-color 154 | dev: true 155 | 156 | /@babel/helper-plugin-utils/7.19.0: 157 | resolution: {integrity: sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==} 158 | engines: {node: '>=6.9.0'} 159 | dev: true 160 | 161 | /@babel/helper-simple-access/7.18.6: 162 | resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==} 163 | engines: {node: '>=6.9.0'} 164 | dependencies: 165 | '@babel/types': 7.19.0 166 | dev: true 167 | 168 | /@babel/helper-split-export-declaration/7.18.6: 169 | resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} 170 | engines: {node: '>=6.9.0'} 171 | dependencies: 172 | '@babel/types': 7.19.0 173 | dev: true 174 | 175 | /@babel/helper-string-parser/7.18.10: 176 | resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==} 177 | engines: {node: '>=6.9.0'} 178 | dev: true 179 | 180 | /@babel/helper-validator-identifier/7.18.6: 181 | resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==} 182 | engines: {node: '>=6.9.0'} 183 | dev: true 184 | 185 | /@babel/helper-validator-option/7.18.6: 186 | resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} 187 | engines: {node: '>=6.9.0'} 188 | dev: true 189 | 190 | /@babel/helpers/7.19.0: 191 | resolution: {integrity: sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==} 192 | engines: {node: '>=6.9.0'} 193 | dependencies: 194 | '@babel/template': 7.18.10 195 | '@babel/traverse': 7.19.0 196 | '@babel/types': 7.19.0 197 | transitivePeerDependencies: 198 | - supports-color 199 | dev: true 200 | 201 | /@babel/highlight/7.18.6: 202 | resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} 203 | engines: {node: '>=6.9.0'} 204 | dependencies: 205 | '@babel/helper-validator-identifier': 7.18.6 206 | chalk: 2.4.2 207 | js-tokens: 4.0.0 208 | dev: true 209 | 210 | /@babel/parser/7.19.0: 211 | resolution: {integrity: sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==} 212 | engines: {node: '>=6.0.0'} 213 | hasBin: true 214 | dependencies: 215 | '@babel/types': 7.19.0 216 | dev: true 217 | 218 | /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.19.0: 219 | resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} 220 | engines: {node: '>=6.9.0'} 221 | peerDependencies: 222 | '@babel/core': ^7.0.0-0 223 | dependencies: 224 | '@babel/core': 7.19.0 225 | '@babel/helper-plugin-utils': 7.19.0 226 | dev: true 227 | 228 | /@babel/plugin-transform-react-jsx-development/7.18.6_@babel+core@7.19.0: 229 | resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==} 230 | engines: {node: '>=6.9.0'} 231 | peerDependencies: 232 | '@babel/core': ^7.0.0-0 233 | dependencies: 234 | '@babel/core': 7.19.0 235 | '@babel/plugin-transform-react-jsx': 7.19.0_@babel+core@7.19.0 236 | dev: true 237 | 238 | /@babel/plugin-transform-react-jsx-self/7.18.6_@babel+core@7.19.0: 239 | resolution: {integrity: sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==} 240 | engines: {node: '>=6.9.0'} 241 | peerDependencies: 242 | '@babel/core': ^7.0.0-0 243 | dependencies: 244 | '@babel/core': 7.19.0 245 | '@babel/helper-plugin-utils': 7.19.0 246 | dev: true 247 | 248 | /@babel/plugin-transform-react-jsx-source/7.18.6_@babel+core@7.19.0: 249 | resolution: {integrity: sha512-utZmlASneDfdaMh0m/WausbjUjEdGrQJz0vFK93d7wD3xf5wBtX219+q6IlCNZeguIcxS2f/CvLZrlLSvSHQXw==} 250 | engines: {node: '>=6.9.0'} 251 | peerDependencies: 252 | '@babel/core': ^7.0.0-0 253 | dependencies: 254 | '@babel/core': 7.19.0 255 | '@babel/helper-plugin-utils': 7.19.0 256 | dev: true 257 | 258 | /@babel/plugin-transform-react-jsx/7.19.0_@babel+core@7.19.0: 259 | resolution: {integrity: sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==} 260 | engines: {node: '>=6.9.0'} 261 | peerDependencies: 262 | '@babel/core': ^7.0.0-0 263 | dependencies: 264 | '@babel/core': 7.19.0 265 | '@babel/helper-annotate-as-pure': 7.18.6 266 | '@babel/helper-module-imports': 7.18.6 267 | '@babel/helper-plugin-utils': 7.19.0 268 | '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.19.0 269 | '@babel/types': 7.19.0 270 | dev: true 271 | 272 | /@babel/runtime/7.19.0: 273 | resolution: {integrity: sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==} 274 | engines: {node: '>=6.9.0'} 275 | dependencies: 276 | regenerator-runtime: 0.13.9 277 | dev: false 278 | 279 | /@babel/template/7.18.10: 280 | resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} 281 | engines: {node: '>=6.9.0'} 282 | dependencies: 283 | '@babel/code-frame': 7.18.6 284 | '@babel/parser': 7.19.0 285 | '@babel/types': 7.19.0 286 | dev: true 287 | 288 | /@babel/traverse/7.19.0: 289 | resolution: {integrity: sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA==} 290 | engines: {node: '>=6.9.0'} 291 | dependencies: 292 | '@babel/code-frame': 7.18.6 293 | '@babel/generator': 7.19.0 294 | '@babel/helper-environment-visitor': 7.18.9 295 | '@babel/helper-function-name': 7.19.0 296 | '@babel/helper-hoist-variables': 7.18.6 297 | '@babel/helper-split-export-declaration': 7.18.6 298 | '@babel/parser': 7.19.0 299 | '@babel/types': 7.19.0 300 | debug: 4.3.4 301 | globals: 11.12.0 302 | transitivePeerDependencies: 303 | - supports-color 304 | dev: true 305 | 306 | /@babel/types/7.19.0: 307 | resolution: {integrity: sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==} 308 | engines: {node: '>=6.9.0'} 309 | dependencies: 310 | '@babel/helper-string-parser': 7.18.10 311 | '@babel/helper-validator-identifier': 7.18.6 312 | to-fast-properties: 2.0.0 313 | dev: true 314 | 315 | /@chevrotain/cst-dts-gen/10.3.0: 316 | resolution: {integrity: sha512-7DJPfCtfK1SU1/F3ZmmVv5IsTTcP/iiKFqU1m0H4VzJNvG3/GNxJFQjy4t/veWTAFSPWSj1WCNyq+sc5XKq9yA==} 317 | dependencies: 318 | '@chevrotain/gast': 10.3.0 319 | '@chevrotain/types': 10.3.0 320 | lodash: 4.17.21 321 | dev: false 322 | 323 | /@chevrotain/gast/10.3.0: 324 | resolution: {integrity: sha512-kLbGubyLprlyFZ1/c5pkpciCi6WTcRcnKhkfflSdKsZuoy0OmVTEXzrmFCQWzJ+QtmQNtPZTKwIBXJ6Zixp6nA==} 325 | dependencies: 326 | '@chevrotain/types': 10.3.0 327 | lodash: 4.17.21 328 | dev: false 329 | 330 | /@chevrotain/types/10.3.0: 331 | resolution: {integrity: sha512-LGesL4c5+FyweDsmFukcxmsowpagj1iC4iqkQSIDG3Y7krV2rIOmCDDq4kZff51Asr6yQHEJsWTyvGVHeWQLkw==} 332 | dev: false 333 | 334 | /@chevrotain/utils/10.3.0: 335 | resolution: {integrity: sha512-KCpFcX+kNyKlVZQW60ZUGRW5Nsg5u0F2CIgHiDQyg282ouHS9xap2ZEKqhwGE/0nYP46nAPnGPdb/IYh7ZHOsA==} 336 | dev: false 337 | 338 | /@esbuild/linux-loong64/0.15.7: 339 | resolution: {integrity: sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==} 340 | engines: {node: '>=12'} 341 | cpu: [loong64] 342 | os: [linux] 343 | requiresBuild: true 344 | dev: true 345 | optional: true 346 | 347 | /@jridgewell/gen-mapping/0.1.1: 348 | resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} 349 | engines: {node: '>=6.0.0'} 350 | dependencies: 351 | '@jridgewell/set-array': 1.1.2 352 | '@jridgewell/sourcemap-codec': 1.4.14 353 | dev: true 354 | 355 | /@jridgewell/gen-mapping/0.3.2: 356 | resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} 357 | engines: {node: '>=6.0.0'} 358 | dependencies: 359 | '@jridgewell/set-array': 1.1.2 360 | '@jridgewell/sourcemap-codec': 1.4.14 361 | '@jridgewell/trace-mapping': 0.3.15 362 | dev: true 363 | 364 | /@jridgewell/resolve-uri/3.1.0: 365 | resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} 366 | engines: {node: '>=6.0.0'} 367 | dev: true 368 | 369 | /@jridgewell/set-array/1.1.2: 370 | resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} 371 | engines: {node: '>=6.0.0'} 372 | dev: true 373 | 374 | /@jridgewell/sourcemap-codec/1.4.14: 375 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} 376 | dev: true 377 | 378 | /@jridgewell/trace-mapping/0.3.15: 379 | resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==} 380 | dependencies: 381 | '@jridgewell/resolve-uri': 3.1.0 382 | '@jridgewell/sourcemap-codec': 1.4.14 383 | dev: true 384 | 385 | /@radix-ui/popper/0.1.0: 386 | resolution: {integrity: sha512-uzYeElL3w7SeNMuQpXiFlBhTT+JyaNMCwDfjKkrzugEcYrf5n52PHqncNdQPUtR42hJh8V9FsqyEDbDxkeNjJQ==} 387 | dependencies: 388 | '@babel/runtime': 7.19.0 389 | csstype: 3.1.0 390 | dev: false 391 | 392 | /@radix-ui/primitive/0.1.0: 393 | resolution: {integrity: sha512-tqxZKybwN5Fa3VzZry4G6mXAAb9aAqKmPtnVbZpL0vsBwvOHTBwsjHVPXylocYLwEtBY9SCe665bYnNB515uoA==} 394 | dependencies: 395 | '@babel/runtime': 7.19.0 396 | dev: false 397 | 398 | /@radix-ui/react-arrow/0.1.3_react@18.2.0: 399 | resolution: {integrity: sha512-9x1gRYdlUD5OUwY7L+M+4FY/YltDSsrNSj8QXGPbxZxL5ghWXB/4lhyIGccCwk/e8ggfmQYv9SRNmn3LavPo3A==} 400 | peerDependencies: 401 | react: ^16.8 || ^17.0 402 | dependencies: 403 | '@babel/runtime': 7.19.0 404 | '@radix-ui/react-primitive': 0.1.3_react@18.2.0 405 | react: 18.2.0 406 | dev: false 407 | 408 | /@radix-ui/react-compose-refs/0.1.0_react@18.2.0: 409 | resolution: {integrity: sha512-eyclbh+b77k+69Dk72q3694OHrn9B3QsoIRx7ywX341U9RK1ThgQjMFZoPtmZNQTksXHLNEiefR8hGVeFyInGg==} 410 | peerDependencies: 411 | react: ^16.8 || ^17.0 412 | dependencies: 413 | '@babel/runtime': 7.19.0 414 | react: 18.2.0 415 | dev: false 416 | 417 | /@radix-ui/react-context/0.1.1_react@18.2.0: 418 | resolution: {integrity: sha512-PkyVX1JsLBioeu0jB9WvRpDBBLtLZohVDT3BB5CTSJqActma8S8030P57mWZb4baZifMvN7KKWPAA40UmWKkQg==} 419 | peerDependencies: 420 | react: ^16.8 || ^17.0 421 | dependencies: 422 | '@babel/runtime': 7.19.0 423 | react: 18.2.0 424 | dev: false 425 | 426 | /@radix-ui/react-id/0.1.4_react@18.2.0: 427 | resolution: {integrity: sha512-/hq5m/D0ZfJWOS7TLF+G0l08KDRs87LBE46JkAvgKkg1fW4jkucx9At9D9vauIPSbdNmww5kXEp566hMlA8eXA==} 428 | peerDependencies: 429 | react: ^16.8 || ^17.0 430 | dependencies: 431 | '@babel/runtime': 7.19.0 432 | '@radix-ui/react-use-layout-effect': 0.1.0_react@18.2.0 433 | react: 18.2.0 434 | dev: false 435 | 436 | /@radix-ui/react-popper/0.1.3_react@18.2.0: 437 | resolution: {integrity: sha512-2OV2YaJv7iTZexJY3HJ7B6Fs1A/3JXd3fRGU4JY0guACfGMD1C/jSgds505MKQOTiHE/quI6j3/q8yfzFjJR9g==} 438 | peerDependencies: 439 | react: ^16.8 || ^17.0 440 | dependencies: 441 | '@babel/runtime': 7.19.0 442 | '@radix-ui/popper': 0.1.0 443 | '@radix-ui/react-arrow': 0.1.3_react@18.2.0 444 | '@radix-ui/react-compose-refs': 0.1.0_react@18.2.0 445 | '@radix-ui/react-context': 0.1.1_react@18.2.0 446 | '@radix-ui/react-primitive': 0.1.3_react@18.2.0 447 | '@radix-ui/react-use-rect': 0.1.1_react@18.2.0 448 | '@radix-ui/react-use-size': 0.1.0_react@18.2.0 449 | '@radix-ui/rect': 0.1.1 450 | react: 18.2.0 451 | dev: false 452 | 453 | /@radix-ui/react-portal/0.1.3_biqbaboplfbrettd7655fr4n2y: 454 | resolution: {integrity: sha512-DrV+sPYLs0HhmX5/b7yRT6nLM9Nl6FtQe2KUG+46kiCOKQ+0XzNMO5hmeQtyq0mRf/qlC02rFu6OMsWpIqVsJg==} 455 | peerDependencies: 456 | react: ^16.8 || ^17.0 457 | react-dom: ^16.8 || ^17.0 458 | dependencies: 459 | '@babel/runtime': 7.19.0 460 | '@radix-ui/react-primitive': 0.1.3_react@18.2.0 461 | '@radix-ui/react-use-layout-effect': 0.1.0_react@18.2.0 462 | react: 18.2.0 463 | react-dom: 18.2.0_react@18.2.0 464 | dev: false 465 | 466 | /@radix-ui/react-portal/0.1.4_biqbaboplfbrettd7655fr4n2y: 467 | resolution: {integrity: sha512-MO0wRy2eYRTZ/CyOri9NANCAtAtq89DEtg90gicaTlkCfdqCLEBsLb+/q66BZQTr3xX/Vq01nnVfc/TkCqoqvw==} 468 | peerDependencies: 469 | react: ^16.8 || ^17.0 470 | react-dom: ^16.8 || ^17.0 471 | dependencies: 472 | '@babel/runtime': 7.19.0 473 | '@radix-ui/react-primitive': 0.1.4_react@18.2.0 474 | '@radix-ui/react-use-layout-effect': 0.1.0_react@18.2.0 475 | react: 18.2.0 476 | react-dom: 18.2.0_react@18.2.0 477 | dev: false 478 | 479 | /@radix-ui/react-presence/0.1.1_react@18.2.0: 480 | resolution: {integrity: sha512-LsL+NcWDpFUAYCmXeH02o4pgqcSLpwxP84UIjCtpIKrsPe2vLuhcp79KC/jZJeXz+of2lUpMAxpM+eCpxFZtlg==} 481 | peerDependencies: 482 | react: '>=16.8' 483 | dependencies: 484 | '@babel/runtime': 7.19.0 485 | '@radix-ui/react-compose-refs': 0.1.0_react@18.2.0 486 | '@radix-ui/react-use-layout-effect': 0.1.0_react@18.2.0 487 | react: 18.2.0 488 | dev: false 489 | 490 | /@radix-ui/react-primitive/0.1.3_react@18.2.0: 491 | resolution: {integrity: sha512-fcyADaaAx2jdqEDLsTs6aX50S3L1c9K9CC6XMpJpuXFJCU4n9PGTFDZRtY2gAoXXoRCPIBsklCopSmGb6SsDjQ==} 492 | peerDependencies: 493 | react: ^16.8 || ^17.0 494 | dependencies: 495 | '@babel/runtime': 7.19.0 496 | '@radix-ui/react-slot': 0.1.2_react@18.2.0 497 | react: 18.2.0 498 | dev: false 499 | 500 | /@radix-ui/react-primitive/0.1.4_react@18.2.0: 501 | resolution: {integrity: sha512-6gSl2IidySupIMJFjYnDIkIWRyQdbu/AHK7rbICPani+LW4b0XdxBXc46og/iZvuwW8pjCS8I2SadIerv84xYA==} 502 | peerDependencies: 503 | react: ^16.8 || ^17.0 504 | dependencies: 505 | '@babel/runtime': 7.19.0 506 | '@radix-ui/react-slot': 0.1.2_react@18.2.0 507 | react: 18.2.0 508 | dev: false 509 | 510 | /@radix-ui/react-slot/0.1.2_react@18.2.0: 511 | resolution: {integrity: sha512-ADkqfL+agEzEguU3yS26jfB50hRrwf7U4VTwAOZEmi/g+ITcBWe12yM46ueS/UCIMI9Py+gFUaAdxgxafFvY2Q==} 512 | peerDependencies: 513 | react: ^16.8 || ^17.0 514 | dependencies: 515 | '@babel/runtime': 7.19.0 516 | '@radix-ui/react-compose-refs': 0.1.0_react@18.2.0 517 | react: 18.2.0 518 | dev: false 519 | 520 | /@radix-ui/react-tooltip/0.1.6_biqbaboplfbrettd7655fr4n2y: 521 | resolution: {integrity: sha512-0uaRpRmTCQo5yMUkDpv4LEDnaQDoeLXcNNhZonCZdbZBQ7ntvjURIWIigq1/pXZp0UX7oPpFzsXD9jUp8JT0WA==} 522 | peerDependencies: 523 | react: ^16.8 || ^17.0 524 | react-dom: ^16.8 || ^17.0 525 | dependencies: 526 | '@babel/runtime': 7.19.0 527 | '@radix-ui/primitive': 0.1.0 528 | '@radix-ui/react-compose-refs': 0.1.0_react@18.2.0 529 | '@radix-ui/react-context': 0.1.1_react@18.2.0 530 | '@radix-ui/react-id': 0.1.4_react@18.2.0 531 | '@radix-ui/react-popper': 0.1.3_react@18.2.0 532 | '@radix-ui/react-portal': 0.1.3_biqbaboplfbrettd7655fr4n2y 533 | '@radix-ui/react-presence': 0.1.1_react@18.2.0 534 | '@radix-ui/react-primitive': 0.1.3_react@18.2.0 535 | '@radix-ui/react-slot': 0.1.2_react@18.2.0 536 | '@radix-ui/react-use-controllable-state': 0.1.0_react@18.2.0 537 | '@radix-ui/react-use-escape-keydown': 0.1.0_react@18.2.0 538 | '@radix-ui/react-use-previous': 0.1.0_react@18.2.0 539 | '@radix-ui/react-use-rect': 0.1.1_react@18.2.0 540 | '@radix-ui/react-visually-hidden': 0.1.3_react@18.2.0 541 | react: 18.2.0 542 | react-dom: 18.2.0_react@18.2.0 543 | dev: false 544 | 545 | /@radix-ui/react-use-callback-ref/0.1.0_react@18.2.0: 546 | resolution: {integrity: sha512-Va041McOFFl+aV+sejvl0BS2aeHx86ND9X/rVFmEFQKTXCp6xgUK0NGUAGcgBlIjnJSbMYPGEk1xKSSlVcN2Aw==} 547 | peerDependencies: 548 | react: ^16.8 || ^17.0 549 | dependencies: 550 | '@babel/runtime': 7.19.0 551 | react: 18.2.0 552 | dev: false 553 | 554 | /@radix-ui/react-use-controllable-state/0.1.0_react@18.2.0: 555 | resolution: {integrity: sha512-zv7CX/PgsRl46a52Tl45TwqwVJdmqnlQEQhaYMz/yBOD2sx2gCkCFSoF/z9mpnYWmS6DTLNTg5lIps3fV6EnXg==} 556 | peerDependencies: 557 | react: ^16.8 || ^17.0 558 | dependencies: 559 | '@babel/runtime': 7.19.0 560 | '@radix-ui/react-use-callback-ref': 0.1.0_react@18.2.0 561 | react: 18.2.0 562 | dev: false 563 | 564 | /@radix-ui/react-use-escape-keydown/0.1.0_react@18.2.0: 565 | resolution: {integrity: sha512-tDLZbTGFmvXaazUXXv8kYbiCcbAE8yKgng9s95d8fCO+Eundv0Jngbn/hKPhDDs4jj9ChwRX5cDDnlaN+ugYYQ==} 566 | peerDependencies: 567 | react: ^16.8 || ^17.0 568 | dependencies: 569 | '@babel/runtime': 7.19.0 570 | '@radix-ui/react-use-callback-ref': 0.1.0_react@18.2.0 571 | react: 18.2.0 572 | dev: false 573 | 574 | /@radix-ui/react-use-layout-effect/0.1.0_react@18.2.0: 575 | resolution: {integrity: sha512-+wdeS51Y+E1q1Wmd+1xSSbesZkpVj4jsg0BojCbopWvgq5iBvixw5vgemscdh58ep98BwUbsFYnrywFhV9yrVg==} 576 | peerDependencies: 577 | react: ^16.8 || ^17.0 578 | dependencies: 579 | '@babel/runtime': 7.19.0 580 | react: 18.2.0 581 | dev: false 582 | 583 | /@radix-ui/react-use-previous/0.1.0_react@18.2.0: 584 | resolution: {integrity: sha512-0fxNc33rYnCzDMPSiSnfS8YklnxQo8WqbAQXPAgIaaA1jRu2qFB916PL4qCIW+avcAAqFD38vWhqDqcVmBharA==} 585 | peerDependencies: 586 | react: ^16.8 || ^17.0 587 | dependencies: 588 | '@babel/runtime': 7.19.0 589 | react: 18.2.0 590 | dev: false 591 | 592 | /@radix-ui/react-use-rect/0.1.1_react@18.2.0: 593 | resolution: {integrity: sha512-kHNNXAsP3/PeszEmM/nxBBS9Jbo93sO+xuMTcRfwzXsmxT5gDXQzAiKbZQ0EecCPtJIzqvr7dlaQi/aP1PKYqQ==} 594 | peerDependencies: 595 | react: ^16.8 || ^17.0 596 | dependencies: 597 | '@babel/runtime': 7.19.0 598 | '@radix-ui/rect': 0.1.1 599 | react: 18.2.0 600 | dev: false 601 | 602 | /@radix-ui/react-use-size/0.1.0_react@18.2.0: 603 | resolution: {integrity: sha512-TcZAsR+BYI46w/RbaSFCRACl+Jh6mDqhu6GS2r0iuJpIVrj8atff7qtTjmMmfGtEDNEjhl7DxN3pr1nTS/oruQ==} 604 | peerDependencies: 605 | react: ^16.8 || ^17.0 606 | dependencies: 607 | '@babel/runtime': 7.19.0 608 | react: 18.2.0 609 | dev: false 610 | 611 | /@radix-ui/react-visually-hidden/0.1.3_react@18.2.0: 612 | resolution: {integrity: sha512-dPU6ZR2WQ/W9qv7E1Y8/I8ymqG+8sViU6dQQ6sfr2/8yGr0I4mmI7ywTnqXaE+YS9gHLEZHdQcEqTNESg6YfdQ==} 613 | peerDependencies: 614 | react: ^16.8 || ^17.0 615 | dependencies: 616 | '@babel/runtime': 7.19.0 617 | '@radix-ui/react-primitive': 0.1.3_react@18.2.0 618 | react: 18.2.0 619 | dev: false 620 | 621 | /@radix-ui/rect/0.1.1: 622 | resolution: {integrity: sha512-g3hnE/UcOg7REdewduRPAK88EPuLZtaq7sA9ouu8S+YEtnyFRI16jgv6GZYe3VMoQLL1T171ebmEPtDjyxWLzw==} 623 | dependencies: 624 | '@babel/runtime': 7.19.0 625 | dev: false 626 | 627 | /@react-spring/animated/9.5.2_react@18.2.0: 628 | resolution: {integrity: sha512-oRlX+MmYLbK8IuUZR7SQUnRjXxJ4PMIZeBkBd1SUWVgVJAHMTfJzPltzm+I6p59qX+qLlklYHfnWaonQKDqLuQ==} 629 | peerDependencies: 630 | react: ^16.8.0 || >=17.0.0 || >=18.0.0 631 | dependencies: 632 | '@react-spring/shared': 9.5.2_react@18.2.0 633 | '@react-spring/types': 9.5.2 634 | react: 18.2.0 635 | dev: false 636 | 637 | /@react-spring/core/9.5.2_react@18.2.0: 638 | resolution: {integrity: sha512-UMRtFH6EfebMp/NMDGCUY5+hZFXsg9iT9hzt/iPzJSz2WMXKBjLoFZHJXcmiVOrIhzHmg1O0pFECn1Wp6pZ5Gw==} 639 | peerDependencies: 640 | react: ^16.8.0 || >=17.0.0 || >=18.0.0 641 | dependencies: 642 | '@react-spring/animated': 9.5.2_react@18.2.0 643 | '@react-spring/rafz': 9.5.2 644 | '@react-spring/shared': 9.5.2_react@18.2.0 645 | '@react-spring/types': 9.5.2 646 | react: 18.2.0 647 | dev: false 648 | 649 | /@react-spring/rafz/9.5.2: 650 | resolution: {integrity: sha512-xHSRXKKBI/wDUkZGrspkOm4VlgN6lZi8Tw9Jzibp9QKf3neoof+U2mDNgklvnLaasymtUwAq9o4ZfFvQIVNgPQ==} 651 | dev: false 652 | 653 | /@react-spring/shared/9.5.2_react@18.2.0: 654 | resolution: {integrity: sha512-/OSf2sjwY4BUnjZL6xMC+H3WxOOhMUCk+yZwgdj40XuyUpk6E6tYyiPeD9Yq5GLsZHodkvE1syVMRVReL4ndAg==} 655 | peerDependencies: 656 | react: ^16.8.0 || >=17.0.0 || >=18.0.0 657 | dependencies: 658 | '@react-spring/rafz': 9.5.2 659 | '@react-spring/types': 9.5.2 660 | react: 18.2.0 661 | dev: false 662 | 663 | /@react-spring/three/9.5.2_2a6gtlagoszca3momc2bks73vi: 664 | resolution: {integrity: sha512-3H7Lv8BJZ3dajh0yJA3m9rEbqz5ZNrTCAkhVOeLqgvBlcWU5qVs4luYA1Z7H4vZnLqVtzv+kHAyg3XIpuTOXhQ==} 665 | peerDependencies: 666 | '@react-three/fiber': '>=6.0' 667 | react: ^16.11.0 || >=17.0.0 || >=18.0.0 668 | three: '>=0.126' 669 | dependencies: 670 | '@react-spring/animated': 9.5.2_react@18.2.0 671 | '@react-spring/core': 9.5.2_react@18.2.0 672 | '@react-spring/shared': 9.5.2_react@18.2.0 673 | '@react-spring/types': 9.5.2 674 | '@react-three/fiber': 8.7.2_ww22p6cticflcq7fk2rysgxj34 675 | react: 18.2.0 676 | three: 0.144.0 677 | dev: false 678 | 679 | /@react-spring/types/9.5.2: 680 | resolution: {integrity: sha512-n/wBRSHPqTmEd4BFWY6TeR1o/UY+3ujoqMxLjqy90CcY/ozJzDRuREL3c+pxMeTF2+B7dX33dTPCtFMX51nbxg==} 681 | dev: false 682 | 683 | /@react-three/drei/9.29.1_gjrj76muidflkn6okfckfwmak4: 684 | resolution: {integrity: sha512-mT1r8pko66Ws8KC9oszuwpym7fiklfewqACZ+eX3oyTsSeUc2FtmbaJB4KZdV2lyrph9+A4Ex9b1JCfQLKqGlA==} 685 | peerDependencies: 686 | '@react-three/fiber': '>=8.0' 687 | react: '>=18.0' 688 | react-dom: '>=18.0' 689 | three: '>=0.137' 690 | peerDependenciesMeta: 691 | react-dom: 692 | optional: true 693 | dependencies: 694 | '@babel/runtime': 7.19.0 695 | '@react-spring/three': 9.5.2_2a6gtlagoszca3momc2bks73vi 696 | '@react-three/fiber': 8.7.2_ww22p6cticflcq7fk2rysgxj34 697 | '@use-gesture/react': 10.2.19_react@18.2.0 698 | detect-gpu: 4.0.38 699 | glsl-noise: 0.0.0 700 | lodash.clamp: 4.0.3 701 | lodash.omit: 4.5.0 702 | lodash.pick: 4.4.0 703 | meshline: 2.0.4_three@0.144.0 704 | react: 18.2.0 705 | react-composer: 5.0.3_react@18.2.0 706 | react-dom: 18.2.0_react@18.2.0 707 | react-merge-refs: 1.1.0 708 | stats.js: 0.17.0 709 | suspend-react: 0.0.8_react@18.2.0 710 | three: 0.144.0 711 | three-mesh-bvh: 0.5.16_three@0.144.0 712 | three-stdlib: 2.15.0_three@0.144.0 713 | troika-three-text: 0.46.4_three@0.144.0 714 | utility-types: 3.10.0 715 | zustand: 3.7.2_react@18.2.0 716 | dev: false 717 | 718 | /@react-three/fiber/8.7.2_ww22p6cticflcq7fk2rysgxj34: 719 | resolution: {integrity: sha512-tV9XjVUhCE+yZgY5dPHoEJi9+LmPZemJfVC9oVItT+sGm/uVMC7pEMUzmfo3Igax7KiL7lyQHM7sJOJKFtbuNg==} 720 | peerDependencies: 721 | expo: '>=43.0' 722 | expo-asset: '>=8.4' 723 | expo-gl: '>=11.0' 724 | react: '>=18.0' 725 | react-dom: '>=18.0' 726 | react-native: '>=0.64' 727 | three: '>=0.133' 728 | peerDependenciesMeta: 729 | expo: 730 | optional: true 731 | expo-asset: 732 | optional: true 733 | expo-gl: 734 | optional: true 735 | react-dom: 736 | optional: true 737 | react-native: 738 | optional: true 739 | dependencies: 740 | '@babel/runtime': 7.19.0 741 | '@types/react-reconciler': 0.26.7 742 | react: 18.2.0 743 | react-dom: 18.2.0_react@18.2.0 744 | react-reconciler: 0.27.0_react@18.2.0 745 | react-use-measure: 2.1.1_biqbaboplfbrettd7655fr4n2y 746 | scheduler: 0.21.0 747 | suspend-react: 0.0.8_react@18.2.0 748 | three: 0.144.0 749 | zustand: 3.7.2_react@18.2.0 750 | dev: false 751 | 752 | /@stitches/react/1.2.8_react@18.2.0: 753 | resolution: {integrity: sha512-9g9dWI4gsSVe8bNLlb+lMkBYsnIKCZTmvqvDG+Avnn69XfmHZKiaMrx7cgTaddq7aTPPmXiTsbFcUy0xgI4+wA==} 754 | peerDependencies: 755 | react: '>= 16.3.0' 756 | dependencies: 757 | react: 18.2.0 758 | dev: false 759 | 760 | /@types/offscreencanvas/2019.7.0: 761 | resolution: {integrity: sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==} 762 | dev: false 763 | 764 | /@types/prop-types/15.7.5: 765 | resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} 766 | 767 | /@types/react-dom/18.0.6: 768 | resolution: {integrity: sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==} 769 | dependencies: 770 | '@types/react': 18.0.18 771 | dev: true 772 | 773 | /@types/react-reconciler/0.26.7: 774 | resolution: {integrity: sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==} 775 | dependencies: 776 | '@types/react': 18.0.18 777 | dev: false 778 | 779 | /@types/react/18.0.17: 780 | resolution: {integrity: sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==} 781 | dependencies: 782 | '@types/prop-types': 15.7.5 783 | '@types/scheduler': 0.16.2 784 | csstype: 3.1.0 785 | dev: true 786 | 787 | /@types/react/18.0.18: 788 | resolution: {integrity: sha512-6hI08umYs6NaiHFEEGioXnxJ+oEhY3eRz8VCUaudZmGdtvPviCJB8mgaMxaDWAdPSYd4eFavrPk2QIolwbLYrg==} 789 | dependencies: 790 | '@types/prop-types': 15.7.5 791 | '@types/scheduler': 0.16.2 792 | csstype: 3.1.0 793 | 794 | /@types/scheduler/0.16.2: 795 | resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} 796 | 797 | /@types/three/0.144.0: 798 | resolution: {integrity: sha512-psvEs6q5rLN50jUYZ3D4pZMfxTbdt3A243blt0my7/NcL6chaCZpHe2csbCtx0SOD9fI/XnF3wnVUAYZGqCSYg==} 799 | dependencies: 800 | '@types/webxr': 0.5.0 801 | dev: true 802 | 803 | /@types/webxr/0.5.0: 804 | resolution: {integrity: sha512-IUMDPSXnYIbEO2IereEFcgcqfDREOgmbGqtrMpVPpACTU6pltYLwHgVkrnYv0XhWEcjio9sYEfIEzgn3c7nDqA==} 805 | dev: true 806 | 807 | /@use-gesture/core/10.2.19: 808 | resolution: {integrity: sha512-fsvuWmEfDDVgCEChLZuJFO8ZgBQLsEsL40ncv+HWYbkF90SwrLo2lkCu+O9TZa9ipqWC2KBXl27pRODY5ogr4w==} 809 | dev: false 810 | 811 | /@use-gesture/react/10.2.19_react@18.2.0: 812 | resolution: {integrity: sha512-pzRBEHehKKaM0T1bRlvLACfUlFetfaTrNH3mduJlRTsWvgKV+SNhoGxZzIavqyZW1kcIacYeXPr3XfvutpoN2w==} 813 | peerDependencies: 814 | react: '>= 16.8.0' 815 | dependencies: 816 | '@use-gesture/core': 10.2.19 817 | react: 18.2.0 818 | dev: false 819 | 820 | /@vitejs/plugin-react/2.1.0_vite@3.1.0: 821 | resolution: {integrity: sha512-am6rPyyU3LzUYne3Gd9oj9c4Rzbq5hQnuGXSMT6Gujq45Il/+bunwq3lrB7wghLkiF45ygMwft37vgJ/NE8IAA==} 822 | engines: {node: ^14.18.0 || >=16.0.0} 823 | peerDependencies: 824 | vite: ^3.0.0 825 | dependencies: 826 | '@babel/core': 7.19.0 827 | '@babel/plugin-transform-react-jsx': 7.19.0_@babel+core@7.19.0 828 | '@babel/plugin-transform-react-jsx-development': 7.18.6_@babel+core@7.19.0 829 | '@babel/plugin-transform-react-jsx-self': 7.18.6_@babel+core@7.19.0 830 | '@babel/plugin-transform-react-jsx-source': 7.18.6_@babel+core@7.19.0 831 | magic-string: 0.26.3 832 | react-refresh: 0.14.0 833 | vite: 3.1.0 834 | transitivePeerDependencies: 835 | - supports-color 836 | dev: true 837 | 838 | /@webgpu/glslang/0.0.15: 839 | resolution: {integrity: sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q==} 840 | dev: false 841 | 842 | /@welldone-software/why-did-you-render/6.2.3_react@18.2.0: 843 | resolution: {integrity: sha512-FQgi90jvC9uw2aALlonJfqaWOvU5UUBBVvdAnS2iryXwCc4YJkKsPJY5Y/LzaND3OIyk8XGUn1vTRn6hcem28Q==} 844 | peerDependencies: 845 | react: ^16 || ^17 846 | dependencies: 847 | lodash: 4.17.21 848 | react: 18.2.0 849 | dev: false 850 | 851 | /ansi-regex/5.0.1: 852 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 853 | engines: {node: '>=8'} 854 | dev: true 855 | 856 | /ansi-styles/3.2.1: 857 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} 858 | engines: {node: '>=4'} 859 | dependencies: 860 | color-convert: 1.9.3 861 | dev: true 862 | 863 | /ansi-styles/4.3.0: 864 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 865 | engines: {node: '>=8'} 866 | dependencies: 867 | color-convert: 2.0.1 868 | dev: true 869 | 870 | /assign-symbols/1.0.0: 871 | resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} 872 | engines: {node: '>=0.10.0'} 873 | dev: false 874 | 875 | /attr-accept/2.2.2: 876 | resolution: {integrity: sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==} 877 | engines: {node: '>=4'} 878 | dev: false 879 | 880 | /bidi-js/1.0.2: 881 | resolution: {integrity: sha512-rzSy/k7WdX5zOyeHHCOixGXbCHkyogkxPKL2r8QtzHmVQDiWCXUWa18bLdMWT9CYMLOYTjWpTHawuev2ouYJVw==} 882 | dependencies: 883 | require-from-string: 2.0.2 884 | dev: false 885 | 886 | /browserslist/4.21.3: 887 | resolution: {integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==} 888 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 889 | hasBin: true 890 | dependencies: 891 | caniuse-lite: 1.0.30001393 892 | electron-to-chromium: 1.4.244 893 | node-releases: 2.0.6 894 | update-browserslist-db: 1.0.7_browserslist@4.21.3 895 | dev: true 896 | 897 | /caniuse-lite/1.0.30001393: 898 | resolution: {integrity: sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==} 899 | dev: true 900 | 901 | /chalk/2.4.2: 902 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} 903 | engines: {node: '>=4'} 904 | dependencies: 905 | ansi-styles: 3.2.1 906 | escape-string-regexp: 1.0.5 907 | supports-color: 5.5.0 908 | dev: true 909 | 910 | /chevrotain/10.3.0: 911 | resolution: {integrity: sha512-sy3yTBfvNJmxzYOGWaDStZFuA7va5/MXwzBU+XBIol0bR0aYlfGqTjzgedeu32Ki/j7IVyvYAZO2PInBjmmMjg==} 912 | dependencies: 913 | '@chevrotain/cst-dts-gen': 10.3.0 914 | '@chevrotain/gast': 10.3.0 915 | '@chevrotain/types': 10.3.0 916 | '@chevrotain/utils': 10.3.0 917 | lodash: 4.17.21 918 | regexp-to-ast: 0.5.0 919 | dev: false 920 | 921 | /cliui/7.0.4: 922 | resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} 923 | dependencies: 924 | string-width: 4.2.3 925 | strip-ansi: 6.0.1 926 | wrap-ansi: 7.0.0 927 | dev: true 928 | 929 | /color-convert/1.9.3: 930 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 931 | dependencies: 932 | color-name: 1.1.3 933 | dev: true 934 | 935 | /color-convert/2.0.1: 936 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 937 | engines: {node: '>=7.0.0'} 938 | dependencies: 939 | color-name: 1.1.4 940 | dev: true 941 | 942 | /color-name/1.1.3: 943 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 944 | dev: true 945 | 946 | /color-name/1.1.4: 947 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 948 | dev: true 949 | 950 | /colord/2.9.3: 951 | resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} 952 | dev: false 953 | 954 | /convert-source-map/1.8.0: 955 | resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} 956 | dependencies: 957 | safe-buffer: 5.1.2 958 | dev: true 959 | 960 | /csstype/3.1.0: 961 | resolution: {integrity: sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==} 962 | 963 | /debounce/1.2.1: 964 | resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} 965 | dev: false 966 | 967 | /debug/4.3.4: 968 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 969 | engines: {node: '>=6.0'} 970 | peerDependencies: 971 | supports-color: '*' 972 | peerDependenciesMeta: 973 | supports-color: 974 | optional: true 975 | dependencies: 976 | ms: 2.1.2 977 | dev: true 978 | 979 | /define-lazy-prop/2.0.0: 980 | resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} 981 | engines: {node: '>=8'} 982 | dev: true 983 | 984 | /dequal/2.0.3: 985 | resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} 986 | engines: {node: '>=6'} 987 | dev: false 988 | 989 | /detect-gpu/4.0.38: 990 | resolution: {integrity: sha512-rcUSndkHBA6jXq3yKolPHHyur7ypJkjwLQzrv3ONGays6/CPYBLA8fSWqRnNlGaT2J0bGrB5pPYcm5Oyz+xPoQ==} 991 | dependencies: 992 | webgl-constants: 1.1.1 993 | dev: false 994 | 995 | /draco3d/1.5.3: 996 | resolution: {integrity: sha512-Ahum6SewAd1oVMm6Fk8T/zCE0qbzjohhO5pl1Xp5Outl4JKv7jYicfd5vNtkzImx94XE35fhNXVqHk9ajt+6Tg==} 997 | dev: false 998 | 999 | /electron-to-chromium/1.4.244: 1000 | resolution: {integrity: sha512-E21saXLt2eTDaTxgUtiJtBUqanF9A32wZasAwDZ8gvrqXoxrBrbwtDCx7c/PQTLp81wj4X0OLDeoGQg7eMo3+w==} 1001 | dev: true 1002 | 1003 | /emoji-regex/8.0.0: 1004 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 1005 | dev: true 1006 | 1007 | /esbuild-android-64/0.15.7: 1008 | resolution: {integrity: sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==} 1009 | engines: {node: '>=12'} 1010 | cpu: [x64] 1011 | os: [android] 1012 | requiresBuild: true 1013 | dev: true 1014 | optional: true 1015 | 1016 | /esbuild-android-arm64/0.15.7: 1017 | resolution: {integrity: sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==} 1018 | engines: {node: '>=12'} 1019 | cpu: [arm64] 1020 | os: [android] 1021 | requiresBuild: true 1022 | dev: true 1023 | optional: true 1024 | 1025 | /esbuild-darwin-64/0.15.7: 1026 | resolution: {integrity: sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==} 1027 | engines: {node: '>=12'} 1028 | cpu: [x64] 1029 | os: [darwin] 1030 | requiresBuild: true 1031 | dev: true 1032 | optional: true 1033 | 1034 | /esbuild-darwin-arm64/0.15.7: 1035 | resolution: {integrity: sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==} 1036 | engines: {node: '>=12'} 1037 | cpu: [arm64] 1038 | os: [darwin] 1039 | requiresBuild: true 1040 | dev: true 1041 | optional: true 1042 | 1043 | /esbuild-freebsd-64/0.15.7: 1044 | resolution: {integrity: sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==} 1045 | engines: {node: '>=12'} 1046 | cpu: [x64] 1047 | os: [freebsd] 1048 | requiresBuild: true 1049 | dev: true 1050 | optional: true 1051 | 1052 | /esbuild-freebsd-arm64/0.15.7: 1053 | resolution: {integrity: sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==} 1054 | engines: {node: '>=12'} 1055 | cpu: [arm64] 1056 | os: [freebsd] 1057 | requiresBuild: true 1058 | dev: true 1059 | optional: true 1060 | 1061 | /esbuild-linux-32/0.15.7: 1062 | resolution: {integrity: sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==} 1063 | engines: {node: '>=12'} 1064 | cpu: [ia32] 1065 | os: [linux] 1066 | requiresBuild: true 1067 | dev: true 1068 | optional: true 1069 | 1070 | /esbuild-linux-64/0.15.7: 1071 | resolution: {integrity: sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==} 1072 | engines: {node: '>=12'} 1073 | cpu: [x64] 1074 | os: [linux] 1075 | requiresBuild: true 1076 | dev: true 1077 | optional: true 1078 | 1079 | /esbuild-linux-arm/0.15.7: 1080 | resolution: {integrity: sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==} 1081 | engines: {node: '>=12'} 1082 | cpu: [arm] 1083 | os: [linux] 1084 | requiresBuild: true 1085 | dev: true 1086 | optional: true 1087 | 1088 | /esbuild-linux-arm64/0.15.7: 1089 | resolution: {integrity: sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==} 1090 | engines: {node: '>=12'} 1091 | cpu: [arm64] 1092 | os: [linux] 1093 | requiresBuild: true 1094 | dev: true 1095 | optional: true 1096 | 1097 | /esbuild-linux-mips64le/0.15.7: 1098 | resolution: {integrity: sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==} 1099 | engines: {node: '>=12'} 1100 | cpu: [mips64el] 1101 | os: [linux] 1102 | requiresBuild: true 1103 | dev: true 1104 | optional: true 1105 | 1106 | /esbuild-linux-ppc64le/0.15.7: 1107 | resolution: {integrity: sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==} 1108 | engines: {node: '>=12'} 1109 | cpu: [ppc64] 1110 | os: [linux] 1111 | requiresBuild: true 1112 | dev: true 1113 | optional: true 1114 | 1115 | /esbuild-linux-riscv64/0.15.7: 1116 | resolution: {integrity: sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==} 1117 | engines: {node: '>=12'} 1118 | cpu: [riscv64] 1119 | os: [linux] 1120 | requiresBuild: true 1121 | dev: true 1122 | optional: true 1123 | 1124 | /esbuild-linux-s390x/0.15.7: 1125 | resolution: {integrity: sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==} 1126 | engines: {node: '>=12'} 1127 | cpu: [s390x] 1128 | os: [linux] 1129 | requiresBuild: true 1130 | dev: true 1131 | optional: true 1132 | 1133 | /esbuild-netbsd-64/0.15.7: 1134 | resolution: {integrity: sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==} 1135 | engines: {node: '>=12'} 1136 | cpu: [x64] 1137 | os: [netbsd] 1138 | requiresBuild: true 1139 | dev: true 1140 | optional: true 1141 | 1142 | /esbuild-openbsd-64/0.15.7: 1143 | resolution: {integrity: sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==} 1144 | engines: {node: '>=12'} 1145 | cpu: [x64] 1146 | os: [openbsd] 1147 | requiresBuild: true 1148 | dev: true 1149 | optional: true 1150 | 1151 | /esbuild-sunos-64/0.15.7: 1152 | resolution: {integrity: sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==} 1153 | engines: {node: '>=12'} 1154 | cpu: [x64] 1155 | os: [sunos] 1156 | requiresBuild: true 1157 | dev: true 1158 | optional: true 1159 | 1160 | /esbuild-windows-32/0.15.7: 1161 | resolution: {integrity: sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==} 1162 | engines: {node: '>=12'} 1163 | cpu: [ia32] 1164 | os: [win32] 1165 | requiresBuild: true 1166 | dev: true 1167 | optional: true 1168 | 1169 | /esbuild-windows-64/0.15.7: 1170 | resolution: {integrity: sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==} 1171 | engines: {node: '>=12'} 1172 | cpu: [x64] 1173 | os: [win32] 1174 | requiresBuild: true 1175 | dev: true 1176 | optional: true 1177 | 1178 | /esbuild-windows-arm64/0.15.7: 1179 | resolution: {integrity: sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==} 1180 | engines: {node: '>=12'} 1181 | cpu: [arm64] 1182 | os: [win32] 1183 | requiresBuild: true 1184 | dev: true 1185 | optional: true 1186 | 1187 | /esbuild/0.15.7: 1188 | resolution: {integrity: sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==} 1189 | engines: {node: '>=12'} 1190 | hasBin: true 1191 | requiresBuild: true 1192 | optionalDependencies: 1193 | '@esbuild/linux-loong64': 0.15.7 1194 | esbuild-android-64: 0.15.7 1195 | esbuild-android-arm64: 0.15.7 1196 | esbuild-darwin-64: 0.15.7 1197 | esbuild-darwin-arm64: 0.15.7 1198 | esbuild-freebsd-64: 0.15.7 1199 | esbuild-freebsd-arm64: 0.15.7 1200 | esbuild-linux-32: 0.15.7 1201 | esbuild-linux-64: 0.15.7 1202 | esbuild-linux-arm: 0.15.7 1203 | esbuild-linux-arm64: 0.15.7 1204 | esbuild-linux-mips64le: 0.15.7 1205 | esbuild-linux-ppc64le: 0.15.7 1206 | esbuild-linux-riscv64: 0.15.7 1207 | esbuild-linux-s390x: 0.15.7 1208 | esbuild-netbsd-64: 0.15.7 1209 | esbuild-openbsd-64: 0.15.7 1210 | esbuild-sunos-64: 0.15.7 1211 | esbuild-windows-32: 0.15.7 1212 | esbuild-windows-64: 0.15.7 1213 | esbuild-windows-arm64: 0.15.7 1214 | dev: true 1215 | 1216 | /escalade/3.1.1: 1217 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 1218 | engines: {node: '>=6'} 1219 | dev: true 1220 | 1221 | /escape-string-regexp/1.0.5: 1222 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 1223 | engines: {node: '>=0.8.0'} 1224 | dev: true 1225 | 1226 | /extend-shallow/2.0.1: 1227 | resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} 1228 | engines: {node: '>=0.10.0'} 1229 | dependencies: 1230 | is-extendable: 0.1.1 1231 | dev: false 1232 | 1233 | /extend-shallow/3.0.2: 1234 | resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} 1235 | engines: {node: '>=0.10.0'} 1236 | dependencies: 1237 | assign-symbols: 1.0.0 1238 | is-extendable: 1.0.1 1239 | dev: false 1240 | 1241 | /fflate/0.6.10: 1242 | resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==} 1243 | dev: false 1244 | 1245 | /file-selector/0.5.0: 1246 | resolution: {integrity: sha512-s8KNnmIDTBoD0p9uJ9uD0XY38SCeBOtj0UMXyQSLg1Ypfrfj8+dAvwsLjYQkQ2GjhVtp2HrnF5cJzMhBjfD8HA==} 1247 | engines: {node: '>= 10'} 1248 | dependencies: 1249 | tslib: 2.4.0 1250 | dev: false 1251 | 1252 | /for-in/1.0.2: 1253 | resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} 1254 | engines: {node: '>=0.10.0'} 1255 | dev: false 1256 | 1257 | /fsevents/2.3.2: 1258 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 1259 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1260 | os: [darwin] 1261 | requiresBuild: true 1262 | dev: true 1263 | optional: true 1264 | 1265 | /function-bind/1.1.1: 1266 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} 1267 | dev: true 1268 | 1269 | /gensync/1.0.0-beta.2: 1270 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 1271 | engines: {node: '>=6.9.0'} 1272 | dev: true 1273 | 1274 | /get-caller-file/2.0.5: 1275 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} 1276 | engines: {node: 6.* || 8.* || >= 10.*} 1277 | dev: true 1278 | 1279 | /get-value/2.0.6: 1280 | resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} 1281 | engines: {node: '>=0.10.0'} 1282 | dev: false 1283 | 1284 | /globals/11.12.0: 1285 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 1286 | engines: {node: '>=4'} 1287 | dev: true 1288 | 1289 | /glsl-noise/0.0.0: 1290 | resolution: {integrity: sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==} 1291 | dev: false 1292 | 1293 | /has-flag/3.0.0: 1294 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 1295 | engines: {node: '>=4'} 1296 | dev: true 1297 | 1298 | /has/1.0.3: 1299 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} 1300 | engines: {node: '>= 0.4.0'} 1301 | dependencies: 1302 | function-bind: 1.1.1 1303 | dev: true 1304 | 1305 | /immer/9.0.15: 1306 | resolution: {integrity: sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==} 1307 | dev: false 1308 | 1309 | /is-core-module/2.10.0: 1310 | resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} 1311 | dependencies: 1312 | has: 1.0.3 1313 | dev: true 1314 | 1315 | /is-docker/2.2.1: 1316 | resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} 1317 | engines: {node: '>=8'} 1318 | hasBin: true 1319 | dev: true 1320 | 1321 | /is-extendable/0.1.1: 1322 | resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} 1323 | engines: {node: '>=0.10.0'} 1324 | dev: false 1325 | 1326 | /is-extendable/1.0.1: 1327 | resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} 1328 | engines: {node: '>=0.10.0'} 1329 | dependencies: 1330 | is-plain-object: 2.0.4 1331 | dev: false 1332 | 1333 | /is-fullwidth-code-point/3.0.0: 1334 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1335 | engines: {node: '>=8'} 1336 | dev: true 1337 | 1338 | /is-plain-object/2.0.4: 1339 | resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} 1340 | engines: {node: '>=0.10.0'} 1341 | dependencies: 1342 | isobject: 3.0.1 1343 | dev: false 1344 | 1345 | /is-wsl/2.2.0: 1346 | resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} 1347 | engines: {node: '>=8'} 1348 | dependencies: 1349 | is-docker: 2.2.1 1350 | dev: true 1351 | 1352 | /isobject/3.0.1: 1353 | resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} 1354 | engines: {node: '>=0.10.0'} 1355 | dev: false 1356 | 1357 | /js-tokens/4.0.0: 1358 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1359 | 1360 | /jsesc/2.5.2: 1361 | resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} 1362 | engines: {node: '>=4'} 1363 | hasBin: true 1364 | dev: true 1365 | 1366 | /json5/2.2.1: 1367 | resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} 1368 | engines: {node: '>=6'} 1369 | hasBin: true 1370 | dev: true 1371 | 1372 | /ktx-parse/0.4.5: 1373 | resolution: {integrity: sha512-MK3FOody4TXbFf8Yqv7EBbySw7aPvEcPX++Ipt6Sox+/YMFvR5xaTyhfNSk1AEmMy+RYIw81ctN4IMxCB8OAlg==} 1374 | dev: false 1375 | 1376 | /leva/0.9.31_biqbaboplfbrettd7655fr4n2y: 1377 | resolution: {integrity: sha512-qQGz35mKM9BXTFcG9qeB+89lkdvguDriiNWoGU9U8BU8r57Ve+6rFF+X5EPKJKwhmFQSbHIRj3mBZKjCjHor2g==} 1378 | peerDependencies: 1379 | react: '>=16.8.0' 1380 | react-dom: '>=16.8.0' 1381 | dependencies: 1382 | '@radix-ui/react-portal': 0.1.4_biqbaboplfbrettd7655fr4n2y 1383 | '@radix-ui/react-tooltip': 0.1.6_biqbaboplfbrettd7655fr4n2y 1384 | '@stitches/react': 1.2.8_react@18.2.0 1385 | '@use-gesture/react': 10.2.19_react@18.2.0 1386 | '@welldone-software/why-did-you-render': 6.2.3_react@18.2.0 1387 | colord: 2.9.3 1388 | dequal: 2.0.3 1389 | merge-value: 1.0.0 1390 | react: 18.2.0 1391 | react-colorful: 5.6.1_biqbaboplfbrettd7655fr4n2y 1392 | react-dom: 18.2.0_react@18.2.0 1393 | react-dropzone: 12.1.0_react@18.2.0 1394 | v8n: 1.5.1 1395 | zustand: 3.7.2_react@18.2.0 1396 | dev: false 1397 | 1398 | /lodash.clamp/4.0.3: 1399 | resolution: {integrity: sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg==} 1400 | dev: false 1401 | 1402 | /lodash.omit/4.5.0: 1403 | resolution: {integrity: sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==} 1404 | dev: false 1405 | 1406 | /lodash.pick/4.4.0: 1407 | resolution: {integrity: sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==} 1408 | dev: false 1409 | 1410 | /lodash/4.17.21: 1411 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 1412 | dev: false 1413 | 1414 | /loose-envify/1.4.0: 1415 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 1416 | hasBin: true 1417 | dependencies: 1418 | js-tokens: 4.0.0 1419 | dev: false 1420 | 1421 | /magic-string/0.26.3: 1422 | resolution: {integrity: sha512-u1Po0NDyFcwdg2nzHT88wSK0+Rih0N1M+Ph1Sp08k8yvFFU3KR72wryS7e1qMPJypt99WB7fIFVCA92mQrMjrg==} 1423 | engines: {node: '>=12'} 1424 | dependencies: 1425 | sourcemap-codec: 1.4.8 1426 | dev: true 1427 | 1428 | /merge-value/1.0.0: 1429 | resolution: {integrity: sha512-fJMmvat4NeKz63Uv9iHWcPDjCWcCkoiRoajRTEO8hlhUC6rwaHg0QCF9hBOTjZmm4JuglPckPSTtcuJL5kp0TQ==} 1430 | engines: {node: '>=0.10.0'} 1431 | dependencies: 1432 | get-value: 2.0.6 1433 | is-extendable: 1.0.1 1434 | mixin-deep: 1.3.2 1435 | set-value: 2.0.1 1436 | dev: false 1437 | 1438 | /meshline/2.0.4_three@0.144.0: 1439 | resolution: {integrity: sha512-Jh6DJl/zLqA4xsKvGv5950jr2ukyXQE1wgxs8u94cImHrvL6soVIggqjP+2hVHZXGYaKnWszhtjuCbKNeQyYiw==} 1440 | peerDependencies: 1441 | three: '>=0.137' 1442 | dependencies: 1443 | three: 0.144.0 1444 | dev: false 1445 | 1446 | /mixin-deep/1.3.2: 1447 | resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} 1448 | engines: {node: '>=0.10.0'} 1449 | dependencies: 1450 | for-in: 1.0.2 1451 | is-extendable: 1.0.1 1452 | dev: false 1453 | 1454 | /mmd-parser/1.0.4: 1455 | resolution: {integrity: sha512-Qi0VCU46t2IwfGv5KF0+D/t9cizcDug7qnNoy9Ggk7aucp0tssV8IwTMkBlDbm+VqAf3cdQHTCARKSsuS2MYFg==} 1456 | dev: false 1457 | 1458 | /ms/2.1.2: 1459 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1460 | dev: true 1461 | 1462 | /nanoid/3.3.4: 1463 | resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} 1464 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1465 | hasBin: true 1466 | dev: true 1467 | 1468 | /node-releases/2.0.6: 1469 | resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} 1470 | dev: true 1471 | 1472 | /object-assign/4.1.1: 1473 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1474 | engines: {node: '>=0.10.0'} 1475 | dev: false 1476 | 1477 | /open/8.4.0: 1478 | resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==} 1479 | engines: {node: '>=12'} 1480 | dependencies: 1481 | define-lazy-prop: 2.0.0 1482 | is-docker: 2.2.1 1483 | is-wsl: 2.2.0 1484 | dev: true 1485 | 1486 | /opentype.js/1.3.4: 1487 | resolution: {integrity: sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==} 1488 | engines: {node: '>= 8.0.0'} 1489 | hasBin: true 1490 | dependencies: 1491 | string.prototype.codepointat: 0.2.1 1492 | tiny-inflate: 1.0.3 1493 | dev: false 1494 | 1495 | /path-parse/1.0.7: 1496 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1497 | dev: true 1498 | 1499 | /picocolors/1.0.0: 1500 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 1501 | dev: true 1502 | 1503 | /postcss/8.4.16: 1504 | resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==} 1505 | engines: {node: ^10 || ^12 || >=14} 1506 | dependencies: 1507 | nanoid: 3.3.4 1508 | picocolors: 1.0.0 1509 | source-map-js: 1.0.2 1510 | dev: true 1511 | 1512 | /potpack/1.0.2: 1513 | resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} 1514 | dev: false 1515 | 1516 | /prop-types/15.8.1: 1517 | resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} 1518 | dependencies: 1519 | loose-envify: 1.4.0 1520 | object-assign: 4.1.1 1521 | react-is: 16.13.1 1522 | dev: false 1523 | 1524 | /react-colorful/5.6.1_biqbaboplfbrettd7655fr4n2y: 1525 | resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==} 1526 | peerDependencies: 1527 | react: '>=16.8.0' 1528 | react-dom: '>=16.8.0' 1529 | dependencies: 1530 | react: 18.2.0 1531 | react-dom: 18.2.0_react@18.2.0 1532 | dev: false 1533 | 1534 | /react-composer/5.0.3_react@18.2.0: 1535 | resolution: {integrity: sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==} 1536 | peerDependencies: 1537 | react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 1538 | dependencies: 1539 | prop-types: 15.8.1 1540 | react: 18.2.0 1541 | dev: false 1542 | 1543 | /react-dom/18.2.0_react@18.2.0: 1544 | resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} 1545 | peerDependencies: 1546 | react: ^18.2.0 1547 | dependencies: 1548 | loose-envify: 1.4.0 1549 | react: 18.2.0 1550 | scheduler: 0.23.0 1551 | dev: false 1552 | 1553 | /react-dropzone/12.1.0_react@18.2.0: 1554 | resolution: {integrity: sha512-iBYHA1rbopIvtzokEX4QubO6qk5IF/x3BtKGu74rF2JkQDXnwC4uO/lHKpaw4PJIV6iIAYOlwLv2FpiGyqHNog==} 1555 | engines: {node: '>= 10.13'} 1556 | peerDependencies: 1557 | react: '>= 16.8' 1558 | dependencies: 1559 | attr-accept: 2.2.2 1560 | file-selector: 0.5.0 1561 | prop-types: 15.8.1 1562 | react: 18.2.0 1563 | dev: false 1564 | 1565 | /react-is/16.13.1: 1566 | resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} 1567 | dev: false 1568 | 1569 | /react-merge-refs/1.1.0: 1570 | resolution: {integrity: sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==} 1571 | dev: false 1572 | 1573 | /react-reconciler/0.27.0_react@18.2.0: 1574 | resolution: {integrity: sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==} 1575 | engines: {node: '>=0.10.0'} 1576 | peerDependencies: 1577 | react: ^18.0.0 1578 | dependencies: 1579 | loose-envify: 1.4.0 1580 | react: 18.2.0 1581 | scheduler: 0.21.0 1582 | dev: false 1583 | 1584 | /react-refresh/0.14.0: 1585 | resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} 1586 | engines: {node: '>=0.10.0'} 1587 | dev: true 1588 | 1589 | /react-use-measure/2.1.1_biqbaboplfbrettd7655fr4n2y: 1590 | resolution: {integrity: sha512-nocZhN26cproIiIduswYpV5y5lQpSQS1y/4KuvUCjSKmw7ZWIS/+g3aFnX3WdBkyuGUtTLif3UTqnLLhbDoQig==} 1591 | peerDependencies: 1592 | react: '>=16.13' 1593 | react-dom: '>=16.13' 1594 | dependencies: 1595 | debounce: 1.2.1 1596 | react: 18.2.0 1597 | react-dom: 18.2.0_react@18.2.0 1598 | dev: false 1599 | 1600 | /react/18.2.0: 1601 | resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} 1602 | engines: {node: '>=0.10.0'} 1603 | dependencies: 1604 | loose-envify: 1.4.0 1605 | dev: false 1606 | 1607 | /regenerator-runtime/0.13.9: 1608 | resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} 1609 | dev: false 1610 | 1611 | /regexp-to-ast/0.5.0: 1612 | resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==} 1613 | dev: false 1614 | 1615 | /require-directory/2.1.1: 1616 | resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} 1617 | engines: {node: '>=0.10.0'} 1618 | dev: true 1619 | 1620 | /require-from-string/2.0.2: 1621 | resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} 1622 | engines: {node: '>=0.10.0'} 1623 | dev: false 1624 | 1625 | /resolve/1.22.1: 1626 | resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} 1627 | hasBin: true 1628 | dependencies: 1629 | is-core-module: 2.10.0 1630 | path-parse: 1.0.7 1631 | supports-preserve-symlinks-flag: 1.0.0 1632 | dev: true 1633 | 1634 | /rollup-plugin-visualizer/5.8.1: 1635 | resolution: {integrity: sha512-NBT/xN/LWCwDM2/j5vYmjzpEAKHyclo/8Cv8AfTCwgADAG+tLJDy1vzxMw6NO0dSDjmTeRELD9UU3FwknLv0GQ==} 1636 | engines: {node: '>=14'} 1637 | hasBin: true 1638 | peerDependencies: 1639 | rollup: ^2.0.0 1640 | peerDependenciesMeta: 1641 | rollup: 1642 | optional: true 1643 | dependencies: 1644 | nanoid: 3.3.4 1645 | open: 8.4.0 1646 | source-map: 0.7.4 1647 | yargs: 17.5.1 1648 | dev: true 1649 | 1650 | /rollup/2.78.1: 1651 | resolution: {integrity: sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==} 1652 | engines: {node: '>=10.0.0'} 1653 | hasBin: true 1654 | optionalDependencies: 1655 | fsevents: 2.3.2 1656 | dev: true 1657 | 1658 | /safe-buffer/5.1.2: 1659 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} 1660 | dev: true 1661 | 1662 | /scheduler/0.21.0: 1663 | resolution: {integrity: sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==} 1664 | dependencies: 1665 | loose-envify: 1.4.0 1666 | dev: false 1667 | 1668 | /scheduler/0.23.0: 1669 | resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} 1670 | dependencies: 1671 | loose-envify: 1.4.0 1672 | dev: false 1673 | 1674 | /semver/6.3.0: 1675 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} 1676 | hasBin: true 1677 | dev: true 1678 | 1679 | /set-value/2.0.1: 1680 | resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} 1681 | engines: {node: '>=0.10.0'} 1682 | dependencies: 1683 | extend-shallow: 2.0.1 1684 | is-extendable: 0.1.1 1685 | is-plain-object: 2.0.4 1686 | split-string: 3.1.0 1687 | dev: false 1688 | 1689 | /source-map-js/1.0.2: 1690 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 1691 | engines: {node: '>=0.10.0'} 1692 | dev: true 1693 | 1694 | /source-map/0.7.4: 1695 | resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} 1696 | engines: {node: '>= 8'} 1697 | dev: true 1698 | 1699 | /sourcemap-codec/1.4.8: 1700 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} 1701 | dev: true 1702 | 1703 | /split-string/3.1.0: 1704 | resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} 1705 | engines: {node: '>=0.10.0'} 1706 | dependencies: 1707 | extend-shallow: 3.0.2 1708 | dev: false 1709 | 1710 | /stats.js/0.17.0: 1711 | resolution: {integrity: sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==} 1712 | dev: false 1713 | 1714 | /string-width/4.2.3: 1715 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1716 | engines: {node: '>=8'} 1717 | dependencies: 1718 | emoji-regex: 8.0.0 1719 | is-fullwidth-code-point: 3.0.0 1720 | strip-ansi: 6.0.1 1721 | dev: true 1722 | 1723 | /string.prototype.codepointat/0.2.1: 1724 | resolution: {integrity: sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==} 1725 | dev: false 1726 | 1727 | /strip-ansi/6.0.1: 1728 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1729 | engines: {node: '>=8'} 1730 | dependencies: 1731 | ansi-regex: 5.0.1 1732 | dev: true 1733 | 1734 | /supports-color/5.5.0: 1735 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 1736 | engines: {node: '>=4'} 1737 | dependencies: 1738 | has-flag: 3.0.0 1739 | dev: true 1740 | 1741 | /supports-preserve-symlinks-flag/1.0.0: 1742 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1743 | engines: {node: '>= 0.4'} 1744 | dev: true 1745 | 1746 | /suspend-react/0.0.8_react@18.2.0: 1747 | resolution: {integrity: sha512-ZC3r8Hu1y0dIThzsGw0RLZplnX9yXwfItcvaIzJc2VQVi8TGyGDlu92syMB5ulybfvGLHAI5Ghzlk23UBPF8xg==} 1748 | peerDependencies: 1749 | react: '>=17.0' 1750 | dependencies: 1751 | react: 18.2.0 1752 | dev: false 1753 | 1754 | /three-mesh-bvh/0.5.16_three@0.144.0: 1755 | resolution: {integrity: sha512-kN3QGKJNiQQcuiOsjVIkjtPnV3PJa+0Orih2E52afa+kQfs3zfoYt6Kxn6b6RNiAfaQ+7ckwPK0mTVFVl2F2LA==} 1756 | peerDependencies: 1757 | three: '>= 0.123.0' 1758 | dependencies: 1759 | three: 0.144.0 1760 | dev: false 1761 | 1762 | /three-stdlib/2.15.0_three@0.144.0: 1763 | resolution: {integrity: sha512-81jgpEajYB1HczIKAqcG8oEgRPbKJr/8KfxMY3xIHe9kDNw426PckStLt+GVmV15ezOS+QlUFVSuyjSRPpSLsg==} 1764 | peerDependencies: 1765 | three: '>=0.122.0' 1766 | dependencies: 1767 | '@babel/runtime': 7.19.0 1768 | '@types/offscreencanvas': 2019.7.0 1769 | '@webgpu/glslang': 0.0.15 1770 | chevrotain: 10.3.0 1771 | draco3d: 1.5.3 1772 | fflate: 0.6.10 1773 | ktx-parse: 0.4.5 1774 | mmd-parser: 1.0.4 1775 | opentype.js: 1.3.4 1776 | potpack: 1.0.2 1777 | three: 0.144.0 1778 | zstddec: 0.0.2 1779 | dev: false 1780 | 1781 | /three/0.144.0: 1782 | resolution: {integrity: sha512-R8AXPuqfjfRJKkYoTQcTK7A6i3AdO9++2n8ubya/GTU+fEHhYKu1ZooRSCPkx69jbnzT7dD/xEo6eROQTt2lJw==} 1783 | dev: false 1784 | 1785 | /tiny-inflate/1.0.3: 1786 | resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} 1787 | dev: false 1788 | 1789 | /to-fast-properties/2.0.0: 1790 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 1791 | engines: {node: '>=4'} 1792 | dev: true 1793 | 1794 | /troika-three-text/0.46.4_three@0.144.0: 1795 | resolution: {integrity: sha512-Qsv0HhUKTZgSmAJs5wvO7YlBoJSP9TGPLmrg+K9pbQq4lseQdcevbno/WI38bwJBZ/qS56hvfqEzY0zUEFzDIw==} 1796 | peerDependencies: 1797 | three: '>=0.103.0' 1798 | dependencies: 1799 | bidi-js: 1.0.2 1800 | three: 0.144.0 1801 | troika-three-utils: 0.46.0_three@0.144.0 1802 | troika-worker-utils: 0.46.0 1803 | webgl-sdf-generator: 1.1.1 1804 | dev: false 1805 | 1806 | /troika-three-utils/0.46.0_three@0.144.0: 1807 | resolution: {integrity: sha512-llHyrXAcwzr0bpg80GxsIp73N7FuImm4WCrKDJkAqcAsWmE5pfP9+Qzw+oMWK1P/AdHQ79eOrOl9NjyW4aOw0w==} 1808 | peerDependencies: 1809 | three: '>=0.103.0' 1810 | dependencies: 1811 | three: 0.144.0 1812 | dev: false 1813 | 1814 | /troika-worker-utils/0.46.0: 1815 | resolution: {integrity: sha512-bzOx5f2ZBxkFhXtIvDJlLn2AI3bzCkGVbCndl/2dL5QZrwHEKl45OEIilCxYQQWJG1rEbOD9O80tMjoYjw19OA==} 1816 | dev: false 1817 | 1818 | /tslib/2.4.0: 1819 | resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} 1820 | dev: false 1821 | 1822 | /typescript/4.6.4: 1823 | resolution: {integrity: sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==} 1824 | engines: {node: '>=4.2.0'} 1825 | hasBin: true 1826 | dev: true 1827 | 1828 | /update-browserslist-db/1.0.7_browserslist@4.21.3: 1829 | resolution: {integrity: sha512-iN/XYesmZ2RmmWAiI4Z5rq0YqSiv0brj9Ce9CfhNE4xIW2h+MFxcgkxIzZ+ShkFPUkjU3gQ+3oypadD3RAMtrg==} 1830 | hasBin: true 1831 | peerDependencies: 1832 | browserslist: '>= 4.21.0' 1833 | dependencies: 1834 | browserslist: 4.21.3 1835 | escalade: 3.1.1 1836 | picocolors: 1.0.0 1837 | dev: true 1838 | 1839 | /use-sync-external-store/1.2.0_react@18.2.0: 1840 | resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} 1841 | peerDependencies: 1842 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 1843 | dependencies: 1844 | react: 18.2.0 1845 | dev: false 1846 | 1847 | /utility-types/3.10.0: 1848 | resolution: {integrity: sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==} 1849 | engines: {node: '>= 4'} 1850 | dev: false 1851 | 1852 | /v8n/1.5.1: 1853 | resolution: {integrity: sha512-LdabyT4OffkyXFCe9UT+uMkxNBs5rcTVuZClvxQr08D5TUgo1OFKkoT65qYRCsiKBl/usHjpXvP4hHMzzDRj3A==} 1854 | dev: false 1855 | 1856 | /vite/3.1.0: 1857 | resolution: {integrity: sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==} 1858 | engines: {node: ^14.18.0 || >=16.0.0} 1859 | hasBin: true 1860 | peerDependencies: 1861 | less: '*' 1862 | sass: '*' 1863 | stylus: '*' 1864 | terser: ^5.4.0 1865 | peerDependenciesMeta: 1866 | less: 1867 | optional: true 1868 | sass: 1869 | optional: true 1870 | stylus: 1871 | optional: true 1872 | terser: 1873 | optional: true 1874 | dependencies: 1875 | esbuild: 0.15.7 1876 | postcss: 8.4.16 1877 | resolve: 1.22.1 1878 | rollup: 2.78.1 1879 | optionalDependencies: 1880 | fsevents: 2.3.2 1881 | dev: true 1882 | 1883 | /webgl-constants/1.1.1: 1884 | resolution: {integrity: sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==} 1885 | dev: false 1886 | 1887 | /webgl-sdf-generator/1.1.1: 1888 | resolution: {integrity: sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==} 1889 | dev: false 1890 | 1891 | /wrap-ansi/7.0.0: 1892 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1893 | engines: {node: '>=10'} 1894 | dependencies: 1895 | ansi-styles: 4.3.0 1896 | string-width: 4.2.3 1897 | strip-ansi: 6.0.1 1898 | dev: true 1899 | 1900 | /y18n/5.0.8: 1901 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} 1902 | engines: {node: '>=10'} 1903 | dev: true 1904 | 1905 | /yargs-parser/21.1.1: 1906 | resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} 1907 | engines: {node: '>=12'} 1908 | dev: true 1909 | 1910 | /yargs/17.5.1: 1911 | resolution: {integrity: sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==} 1912 | engines: {node: '>=12'} 1913 | dependencies: 1914 | cliui: 7.0.4 1915 | escalade: 3.1.1 1916 | get-caller-file: 2.0.5 1917 | require-directory: 2.1.1 1918 | string-width: 4.2.3 1919 | y18n: 5.0.8 1920 | yargs-parser: 21.1.1 1921 | dev: true 1922 | 1923 | /zstddec/0.0.2: 1924 | resolution: {integrity: sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA==} 1925 | dev: false 1926 | 1927 | /zustand/3.7.2_react@18.2.0: 1928 | resolution: {integrity: sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==} 1929 | engines: {node: '>=12.7.0'} 1930 | peerDependencies: 1931 | react: '>=16.8' 1932 | peerDependenciesMeta: 1933 | react: 1934 | optional: true 1935 | dependencies: 1936 | react: 18.2.0 1937 | dev: false 1938 | 1939 | /zustand/4.1.1_immer@9.0.15+react@18.2.0: 1940 | resolution: {integrity: sha512-h4F3WMqsZgvvaE0n3lThx4MM81Ls9xebjvrABNzf5+jb3/03YjNTSgZXeyrvXDArMeV9untvWXRw1tY+ntPYbA==} 1941 | engines: {node: '>=12.7.0'} 1942 | peerDependencies: 1943 | immer: '>=9.0' 1944 | react: '>=16.8' 1945 | peerDependenciesMeta: 1946 | immer: 1947 | optional: true 1948 | react: 1949 | optional: true 1950 | dependencies: 1951 | immer: 9.0.15 1952 | react: 18.2.0 1953 | use-sync-external-store: 1.2.0_react@18.2.0 1954 | dev: false 1955 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsulpis/3d-terrain-r3f/e3f77989676f56eb16b5411dfb5f2b348c241bab/screenshot.jpg -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | html, 8 | body, 9 | #root { 10 | width: 100%; 11 | height: 100%; 12 | } 13 | 14 | body { 15 | background: #141414; 16 | font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, helvetica neue, 17 | helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif; 18 | } 19 | 20 | canvas { 21 | cursor: grab; 22 | } 23 | 24 | canvas:active { 25 | cursor: grabbing; 26 | } 27 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Canvas } from "@react-three/fiber"; 2 | import { OrbitControls } from "@react-three/drei"; 3 | import "./App.css"; 4 | import { Lights } from "./components/Lights"; 5 | import { Gizmo } from "./components/Gizmo"; 6 | import { GUI } from "./components/GUI"; 7 | import { Terrain } from "./components/Terrain"; 8 | 9 | export default function App() { 10 | return ( 11 | <> 12 | 13 | 18 | 19 | 20 | 27 | 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/colors/useDisplay.ts: -------------------------------------------------------------------------------- 1 | import { useSettings } from "../state/useSettings"; 2 | import { useHeightMap } from "./useHeightMap"; 3 | import { useNaturalColor } from "./useNaturalColor"; 4 | 5 | export function useDisplay() { 6 | const getNaturalColor = useNaturalColor(); 7 | const getHeightMapColor = useHeightMap(); 8 | const display = useSettings((s) => s.display); 9 | 10 | return display === "color" ? getNaturalColor : getHeightMapColor; 11 | } 12 | -------------------------------------------------------------------------------- /src/colors/useHeightMap.ts: -------------------------------------------------------------------------------- 1 | import { Color } from "three"; 2 | 3 | export function useHeightMap() { 4 | const floorColor = new Color().setHSL(0.75, 1, 0.5); 5 | const ceilingColor = new Color().setHSL(0, 1, 0.5); 6 | const zmin = 0.05; 7 | const zmax = 0.5; 8 | 9 | return (height: number): Color => { 10 | const percent = (height - zmin) / (zmax - zmin); 11 | return floorColor.clone().lerpHSL(ceilingColor, percent); 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /src/colors/useNaturalColor.ts: -------------------------------------------------------------------------------- 1 | import { Color, MathUtils } from "three"; 2 | import { useSettings } from "../state/useSettings"; 3 | 4 | export function useNaturalColor() { 5 | const colors = useSettings((s) => s.colors); 6 | 7 | return (height: number): Color => { 8 | const assetType = (() => { 9 | if (height <= colors.Water.value) { 10 | return "Water"; 11 | } else if (height <= colors.Water.value + colors.Shore.value) { 12 | return "Shore"; 13 | } else if (height <= colors.Water.value + colors.Beach.value) { 14 | return "Beach"; 15 | } else if (height <= colors.Water.value + colors.Shrub.value) { 16 | return "Shrub"; 17 | } else if (height <= colors.Water.value + colors.Forest.value) { 18 | return "Forest"; 19 | } else if (height <= colors.Water.value + colors.Stone.value) { 20 | return "Stone"; 21 | } else { 22 | return "Snow"; 23 | } 24 | })(); 25 | const color = new Color(colors[assetType].color); 26 | const hsl = color.getHSL({ h: 0, s: 1, l: 1 }); 27 | 28 | color.setHSL( 29 | hsl.h, 30 | hsl.s * 1.7, 31 | hsl.l * 32 | (height <= colors.Water.value 33 | ? MathUtils.mapLinear( 34 | Math.pow(1 - (colors.Water.value - height) * 1.3, 6), 35 | 0, 36 | 1, 37 | 0, 38 | 1.4 39 | ) 40 | : 1) 41 | ); 42 | 43 | return color; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /src/components/GUI.tsx: -------------------------------------------------------------------------------- 1 | import { button, Leva, useControls } from "leva"; 2 | import { useSettings, Settings } from "../state/useSettings"; 3 | 4 | export function GUI() { 5 | const colors = useSettings((s) => s.colors); 6 | const generation = useSettings((s) => s.generation); 7 | const display = useSettings((s) => s.display); 8 | const setColorValue = useSettings((s) => s.setColorValue); 9 | const setColor = useSettings((s) => s.setColor); 10 | const setGeneration = useSettings((s) => s.setGeneration); 11 | const setDisplay = useSettings((s) => s.setDisplay); 12 | 13 | useControls("Colors", () => { 14 | const res = {} as any; 15 | Object.keys(colors).forEach((color) => { 16 | res[color] = { 17 | value: colors[color].value, 18 | min: 0, 19 | max: 1, 20 | onChange: (v: number) => setColorValue(color, v) 21 | }; 22 | 23 | res[color] = { 24 | value: colors[color].color, 25 | onChange: (v: string) => setColor(color, v) 26 | }; 27 | }); 28 | 29 | return res; 30 | }); 31 | 32 | useControls("Display", () => ({ 33 | HeightMap: { 34 | value: display === "height", 35 | onChange: (v: boolean) => setDisplay(v ? "height" : "color") 36 | } 37 | })); 38 | 39 | const [_, set] = useControls("Generation", () => { 40 | const res = {} as any; 41 | (Object.keys(generation) as Array).forEach((param) => { 42 | res[param] = { 43 | value: generation[param], 44 | min: 0.01, 45 | max: 1, 46 | onChange: (v: number) => setGeneration(param, v) 47 | }; 48 | }); 49 | res["Sea Level"] = { 50 | value: colors.Water.value, 51 | min: 0, 52 | max: 1, 53 | onChange: (v: number) => setColorValue("Water", v / 2) 54 | }; 55 | 56 | return res; 57 | }); 58 | 59 | useControls({ 60 | Regenerate: button(() => set({ Seed: Math.random() })) 61 | }); 62 | 63 | return ; 64 | } 65 | -------------------------------------------------------------------------------- /src/components/Gizmo.tsx: -------------------------------------------------------------------------------- 1 | import { GizmoHelper, GizmoViewport } from "@react-three/drei"; 2 | 3 | export const Gizmo = () => { 4 | return ( 5 | {}}> 6 | 11 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /src/components/Lights.tsx: -------------------------------------------------------------------------------- 1 | import { useRef } from "react"; 2 | import { useHelper } from "@react-three/drei"; 3 | import { DirectionalLight, DirectionalLightHelper } from "three"; 4 | 5 | export function Lights() { 6 | const ref = useRef(null); 7 | 8 | // useHelper(ref, DirectionalLightHelper); 9 | 10 | return ( 11 | 12 | 13 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/components/Terrain.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | import { Object3D, InstancedMesh } from "three"; 3 | import { useProceduralTerrain } from "../geometry/useProceduralTerrain"; 4 | import { TerrainStats } from "./TerrainStats"; 5 | import { useDisplay } from "../colors/useDisplay"; 6 | 7 | const emptyObject = new Object3D(); 8 | 9 | export function Terrain() { 10 | const ref = useRef(null); 11 | 12 | const { dataBlocks, scale } = useProceduralTerrain(); 13 | const getColor = useDisplay(); 14 | 15 | useEffect(() => { 16 | const mesh = ref.current; 17 | if (!mesh) return; 18 | 19 | dataBlocks.forEach(({ x, y, z, height }, i) => { 20 | const color = getColor(height); 21 | 22 | emptyObject.position.set(x, y, z); 23 | emptyObject.updateMatrix(); 24 | 25 | mesh.setMatrixAt?.(i, emptyObject.matrix); 26 | mesh.setColorAt?.(i, color); 27 | }); 28 | 29 | mesh.instanceMatrix.needsUpdate = true; 30 | mesh.instanceColor!.needsUpdate = true; 31 | }, [dataBlocks, getColor]); 32 | 33 | return ( 34 | <> 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /src/components/TerrainStats.tsx: -------------------------------------------------------------------------------- 1 | import { Html } from "@react-three/drei"; 2 | import type { FC } from "react"; 3 | 4 | const numberFormatter = new Intl.NumberFormat(); 5 | 6 | export const TerrainStats: FC<{ blockCount: number }> = ({ blockCount }) => ( 7 | [40, 40, 0]} style={{ color: "white" }}> 8 | {numberFormatter.format(blockCount)}  9 | blocks 10 |
11 | 12 | ({Math.sqrt(blockCount)}x{Math.sqrt(blockCount)}) 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /src/geometry/useFbmNoise.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useMemo } from "react"; 2 | import { MathUtils, Vector2 } from "three"; 3 | import { FBM } from "../lib/three-noise.module"; 4 | import { useSettings } from "../state/useSettings"; 5 | 6 | export function useFbmNoise() { 7 | const generation = useSettings((s) => s.generation); 8 | 9 | const fbm = useMemo( 10 | () => 11 | new FBM({ 12 | seed: generation.Seed, 13 | lacunarity: generation.Detail * 4, 14 | persistance: generation.Fuzzyness * 2 15 | }), 16 | [generation] 17 | ); 18 | 19 | return useCallback( 20 | (vector: Vector2) => 21 | Math.pow( 22 | MathUtils.mapLinear( 23 | fbm.get2(vector), 24 | -1, // 25 | 1, 26 | 0, 27 | 1 28 | ), 29 | 2 30 | ), 31 | [fbm] 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/geometry/useProceduralTerrain.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from "react"; 2 | import { useSettings } from "../state/useSettings"; 3 | import { useFbmNoise } from "./useFbmNoise"; 4 | import { useSquareSurface } from "./useSquareSurface"; 5 | 6 | /** 7 | * Generate a square procedural terrain using a noise function for the relief 8 | */ 9 | export function useProceduralTerrain() { 10 | const { surface, scale } = useSquareSurface(); 11 | 12 | const waterLevel = useSettings((s) => s.colors.Water.value); 13 | const generationScale = useSettings((s) => s.generation.Scale); 14 | const generationHeight = useSettings((s) => s.generation.Height); 15 | const display = useSettings((s) => s.display); 16 | 17 | const getNoiseValue = useFbmNoise(); 18 | 19 | const dataBlocks = useMemo( 20 | () => 21 | surface.map((point) => { 22 | const scaledVector = point.clone().multiplyScalar(scale * generationScale); 23 | const realHeight = getNoiseValue(scaledVector) * generationHeight; 24 | let visibleHeight = realHeight; 25 | 26 | if (display === "color" && realHeight < waterLevel) { 27 | visibleHeight = waterLevel; 28 | } 29 | 30 | return { 31 | x: point.x, 32 | y: point.y, 33 | z: (visibleHeight / scale) * 3, 34 | height: realHeight 35 | }; 36 | }), 37 | [ 38 | surface, 39 | scale, 40 | generationScale, 41 | generationHeight, 42 | waterLevel, 43 | getNoiseValue, 44 | display 45 | ] 46 | ); 47 | 48 | return { dataBlocks, scale }; 49 | } 50 | -------------------------------------------------------------------------------- /src/geometry/useSquareSurface.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from "react"; 2 | import { Vector2 } from "three"; 3 | import { useSettings } from "../state/useSettings"; 4 | 5 | const INTRINSIC_TERRAIN_MAX_SIZE = 500; 6 | const VISIBLE_MAP_SIZE = 8; 7 | 8 | export function useSquareSurface() { 9 | const resolution = useSettings((s) => s.generation.Resolution); 10 | const terrainSize = Math.max(INTRINSIC_TERRAIN_MAX_SIZE * resolution, 20); 11 | 12 | return useMemo(() => { 13 | const surface = []; 14 | const scale = VISIBLE_MAP_SIZE / terrainSize; 15 | 16 | for (let x = -terrainSize / 2; x < terrainSize / 2; x++) { 17 | for (let y = -terrainSize / 2; y < terrainSize / 2; y++) { 18 | surface.push(new Vector2(x, y)); 19 | } 20 | } 21 | return { surface, scale }; 22 | }, [terrainSize]); 23 | } 24 | -------------------------------------------------------------------------------- /src/lib/three-noise.module.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file has been borrowed from the 'three-noise' package by Faraz Shaikh (@CantBeFaraz): 3 | * https://github.com/FarazzShaikh/three-noise/blob/master/build/three-noise.module.js 4 | * 5 | * because at the time of writing there are a couple of issues with said package: 6 | * https://github.com/FarazzShaikh/three-noise/issues 7 | */ 8 | // @ts-nocheck 9 | 10 | import { Vector2, Vector3 } from "three"; 11 | 12 | var definitions_perlin = 13 | '#define GLSLIFY 1\n// From https://github.com/hughsk/glsl-noise/blob/master/periodic/2d.glsl\n\n//\n// GLSL textureless classic 2D noise "cnoise",\n// with an RSL-style periodic variant "pnoise".\n// Author: Stefan Gustavson (stefan.gustavson@liu.se)\n// Version: 2011-08-22\n//\n// Many thanks to Ian McEwan of Ashima Arts for the\n// ideas for permutation and gradient selection.\n//\n// Copyright (c) 2011 Stefan Gustavson. All rights reserved.\n// Distributed under the MIT license. See LICENSE file.\n// https://github.com/ashima/webgl-noise\n//\n\nvec4 mod289(vec4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\n\nvec4 permute(vec4 x) { return mod289(((x * 34.0) + 1.0) * x); }\n\nvec4 taylorInvSqrt(vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }\n\nvec2 fade(vec2 t) { return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); }\n\nfloat map(float value, float min1, float max1, float min2, float max2) {\n return min2 + (value - min1) * (max2 - min2) / (max1 - min1);\n}\n\n// Classic Perlin noise, periodic variant\nfloat perlin(vec2 P) {\n\n vec2 rep = vec2(255.0, 255.0);\n\n vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);\n vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);\n Pi = mod(Pi, rep.xyxy); // To create noise with explicit period\n Pi = mod289(Pi); // To avoid truncation effects in permutation\n vec4 ix = Pi.xzxz;\n vec4 iy = Pi.yyww;\n vec4 fx = Pf.xzxz;\n vec4 fy = Pf.yyww;\n\n vec4 i = permute(permute(ix) + iy);\n\n vec4 gx = fract(i * (1.0 / 41.0)) * 2.0 - 1.0;\n vec4 gy = abs(gx) - 0.5;\n vec4 tx = floor(gx + 0.5);\n gx = gx - tx;\n\n vec2 g00 = vec2(gx.x, gy.x);\n vec2 g10 = vec2(gx.y, gy.y);\n vec2 g01 = vec2(gx.z, gy.z);\n vec2 g11 = vec2(gx.w, gy.w);\n\n vec4 norm = taylorInvSqrt(\n vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)));\n g00 *= norm.x;\n g01 *= norm.y;\n g10 *= norm.z;\n g11 *= norm.w;\n\n float n00 = dot(g00, vec2(fx.x, fy.x));\n float n10 = dot(g10, vec2(fx.y, fy.y));\n float n01 = dot(g01, vec2(fx.z, fy.z));\n float n11 = dot(g11, vec2(fx.w, fy.w));\n\n vec2 fade_xy = fade(Pf.xy);\n vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);\n float n_xy = mix(n_x.x, n_x.y, fade_xy.y);\n return map(2.3 * n_xy, -1.0, 1.0, 0.0, 1.0);\n}\n\nfloat fbm(vec2 pos, vec4 props) {\n float persistance = props.x;\n float lacunarity = props.y;\n float redistribution = props.z;\n int octaves = int(props.w);\n\n float result = 0.0;\n float amplitude = 1.0;\n float frequency = 1.0;\n float maximum = amplitude;\n\n for (int i = 0; i < 2; i++) {\n\n vec2 p = pos.xy * frequency;\n\n float noiseVal = perlin(p);\n result += noiseVal * amplitude;\n\n frequency *= lacunarity;\n amplitude *= persistance;\n maximum += amplitude;\n }\n\n float redistributed = pow(result, redistribution);\n return redistributed / maximum;\n}\n'; // eslint-disable-line 14 | 15 | var p = [ 16 | 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 17 | 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 18 | 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 19 | 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 20 | 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 21 | 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 22 | 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 23 | 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 24 | 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 25 | 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 26 | 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 27 | 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 28 | 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 29 | 128, 195, 78, 66, 215, 61, 156, 180 30 | ]; 31 | 32 | /** 33 | * An implimentation of Perlin Noise by Ken Perlin. 34 | */ 35 | class Perlin { 36 | /** 37 | * 38 | * @param {number} seed Seed Value for PRNG. 39 | */ 40 | constructor(seed) { 41 | const _gradientVecs = [ 42 | // 2D Vecs 43 | new Vector3(1, 1, 0), 44 | new Vector3(-1, 1, 0), 45 | new Vector3(1, -1, 0), 46 | new Vector3(-1, -1, 0), 47 | // + 3D Vecs 48 | new Vector3(1, 0, 1), 49 | new Vector3(-1, 0, 1), 50 | new Vector3(1, 0, -1), 51 | new Vector3(-1, 0, -1), 52 | new Vector3(0, 1, 1), 53 | new Vector3(0, -1, 1), 54 | new Vector3(0, 1, -1), 55 | new Vector3(0, -1, -1) 56 | ]; 57 | 58 | var perm = new Array(512); 59 | var gradP = new Array(512); 60 | 61 | if (!seed) seed = 1; 62 | seed *= 65536; 63 | 64 | seed = Math.floor(seed); 65 | if (seed < 256) { 66 | seed |= seed << 8; 67 | } 68 | 69 | for (var i = 0; i < 256; i++) { 70 | var v; 71 | if (i & 1) { 72 | v = p[i] ^ (seed & 255); 73 | } else { 74 | v = p[i] ^ ((seed >> 8) & 255); 75 | } 76 | 77 | perm[i] = perm[i + 256] = v; 78 | gradP[i] = gradP[i + 256] = _gradientVecs[v % 12]; 79 | } 80 | 81 | this._seed = seed; 82 | 83 | this._offsetMatrix = [ 84 | new Vector3(0, 0, 0), 85 | new Vector3(0, 0, 1), 86 | new Vector3(0, 1, 0), 87 | new Vector3(0, 1, 1), 88 | new Vector3(1, 0, 0), 89 | new Vector3(1, 0, 1), 90 | new Vector3(1, 1, 0), 91 | new Vector3(1, 1, 1) 92 | ]; 93 | 94 | /** 95 | * GLSL Shader Chunk for 2D Perlin Noise. Can be used with 96 | * three-CustomShaderMaterial. 97 | * See: three-CustomShaderMaterial 98 | */ 99 | this.shaderChunk = { 100 | defines: "", 101 | header: definitions_perlin, 102 | main: "", 103 | uniforms: [{ three_noise_seed: this._seed }] 104 | }; 105 | 106 | this.perm = perm; 107 | this.gradP = gradP; 108 | } 109 | 110 | _fade(t) { 111 | return t * t * t * (t * (t * 6 - 15) + 10); 112 | } 113 | 114 | _lerp(a, b, t) { 115 | return (1 - t) * a + t * b; 116 | } 117 | 118 | _gradient(posInCell) { 119 | if (posInCell instanceof Vector3) { 120 | return posInCell.x + this.perm[posInCell.y + this.perm[posInCell.z]]; 121 | } else { 122 | return posInCell.x + this.perm[posInCell.y]; 123 | } 124 | } 125 | 126 | /** 127 | * Maps a number from one range to another. 128 | * @param {number} x Input Number 129 | * @param {number} in_min Current range minimum 130 | * @param {number} in_max Current range maximum 131 | * @param {number} out_min New range minimum 132 | * @param {number} out_max New range maximum 133 | * @returns {number} Input Mapped to range [out_min, out_max] 134 | */ 135 | static map(x, in_min, in_max, out_min, out_max) { 136 | return ((x - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min; 137 | } 138 | 139 | /** 140 | * Samples 2D Perlin Nosie at given coordinates. 141 | * @param {Vector2 | Vector3} input Coordincates to sample at 142 | * @returns {number} Value of Perlin Noise at that coordinate. 143 | */ 144 | get2(input) { 145 | if (input.z !== undefined) input = new Vector2(input.x, input.y); 146 | 147 | const cell = new Vector2(Math.floor(input.x), Math.floor(input.y)); 148 | input.sub(cell); 149 | 150 | cell.x &= 255; 151 | cell.y &= 255; 152 | 153 | const gradiantDot = []; 154 | for (let i = 0; i < 4; i++) { 155 | const s3 = this._offsetMatrix[i * 2]; 156 | const s = new Vector2(s3.x, s3.y); 157 | 158 | const grad3 = this.gradP[this._gradient(new Vector2().addVectors(cell, s))]; 159 | const grad2 = new Vector2(grad3.x, grad3.y); 160 | const dist2 = new Vector2().subVectors(input, s); 161 | 162 | gradiantDot.push(grad2.dot(dist2)); 163 | } 164 | 165 | const u = this._fade(input.x); 166 | const v = this._fade(input.y); 167 | 168 | const value = this._lerp( 169 | this._lerp(gradiantDot[0], gradiantDot[2], u), 170 | this._lerp(gradiantDot[1], gradiantDot[3], u), 171 | v 172 | ); 173 | 174 | return value; 175 | } 176 | 177 | /** 178 | * Samples 3D Perlin Nosie at given coordinates. 179 | * @param {Vector}3 input Coordincates to sample at 180 | * @returns {number} Value of Perlin Noise at that coordinate. 181 | */ 182 | get3(input) { 183 | if (input.z === undefined) throw "Input to Perlin::get3() must be of type Vector3"; 184 | 185 | const cell = new Vector3( 186 | Math.floor(input.x), 187 | Math.floor(input.y), 188 | Math.floor(input.z) 189 | ); 190 | input.sub(cell); 191 | 192 | cell.x &= 255; 193 | cell.y &= 255; 194 | cell.z &= 255; 195 | 196 | const gradiantDot = []; 197 | for (let i = 0; i < 8; i++) { 198 | const s = this._offsetMatrix[i]; 199 | 200 | const grad3 = this.gradP[this._gradient(new Vector3().addVectors(cell, s))]; 201 | const dist2 = new Vector3().subVectors(input, s); 202 | 203 | gradiantDot.push(grad3.dot(dist2)); 204 | } 205 | 206 | const u = this._fade(input.x); 207 | const v = this._fade(input.y); 208 | const w = this._fade(input.z); 209 | 210 | const value = this._lerp( 211 | this._lerp( 212 | this._lerp(gradiantDot[0], gradiantDot[4], u), 213 | this._lerp(gradiantDot[1], gradiantDot[5], u), 214 | w 215 | ), 216 | this._lerp( 217 | this._lerp(gradiantDot[2], gradiantDot[6], u), 218 | this._lerp(gradiantDot[3], gradiantDot[7], u), 219 | w 220 | ), 221 | v 222 | ); 223 | 224 | return value; 225 | } 226 | } 227 | 228 | /** 229 | * This class is an implimentaiton of a Fractal Brownian Motion 230 | * function using Perlin Nosie. 231 | */ 232 | class FBM { 233 | /** 234 | * Create an instance of the FBM class. 235 | * Use this instance to generate fBm noise. 236 | * 237 | * @param {Object} options Options for fBm generaiton. 238 | * @param {number} options.seed Seed for Perlin Noise 239 | * @param {number} options.scale What distance to view the noisemap 240 | * @param {number} options.persistance How much each octave contributes to the overall shape 241 | * @param {number} options.lacunarity How much detail is added or removed at each octave 242 | * @param {number} options.octaves Levels of detail you want you perlin noise to have 243 | * @param {number} options.redistribution Level of flatness within the valleys 244 | */ 245 | constructor(options) { 246 | const { seed, scale, persistance, lacunarity, octaves, redistribution } = options; 247 | this._noise = new Perlin(seed); 248 | this._scale = scale || 1; 249 | this._persistance = persistance || 0.5; 250 | this._lacunarity = lacunarity || 2; 251 | this._octaves = octaves || 6; 252 | this._redistribution = redistribution || 1; 253 | } 254 | 255 | /** 256 | * Sample 2D Perlin Noise with fBm at given 257 | * coordinates. The function will use Perlin_get2 or Perlin_get3 258 | * depending on the input vector's type. 259 | * 260 | * @param {(Vector2 | Vector3)} input Coordinates to sample noise at. 261 | * @returns {number} Normalized noise in the range [0, 1] 262 | */ 263 | get2(input) { 264 | let result = 0; 265 | let amplitude = 1; 266 | let frequency = 1; 267 | let max = amplitude; 268 | 269 | let noiseFunction = this._noise.get2.bind(this._noise); 270 | 271 | for (let i = 0; i < this._octaves; i++) { 272 | const position = new Vector2( 273 | input.x * this._scale * frequency, 274 | input.y * this._scale * frequency 275 | ); 276 | 277 | const noiseVal = noiseFunction(position); 278 | result += noiseVal * amplitude; 279 | 280 | frequency *= this._lacunarity; 281 | amplitude *= this._persistance; 282 | max += amplitude; 283 | } 284 | 285 | const redistributed = Math.pow(result, this._redistribution); 286 | return redistributed / max; 287 | } 288 | 289 | /** 290 | * Sample 3D Perlin Noise with fBm at given 291 | * coordinates. The function will use Perlin_get2 or Perlin_get3 292 | * depending on the input vector's type. 293 | * 294 | * @param {Vector3} input Coordinates to sample noise at. 295 | * @returns {number} Normalized noise in the range [0, 1] 296 | */ 297 | get3(input) { 298 | let result = 0; 299 | let amplitude = 1; 300 | let frequency = 1; 301 | let max = amplitude; 302 | 303 | let noiseFunction = this._noise.get3.bind(this._noise); 304 | 305 | for (let i = 0; i < this._octaves; i++) { 306 | const position = new Vector3( 307 | input.x * this._scale * frequency, 308 | input.y * this._scale * frequency, 309 | input.z * this._scale * frequency 310 | ); 311 | 312 | const noiseVal = noiseFunction(position); 313 | result += noiseVal * amplitude; 314 | 315 | frequency *= this._lacunarity; 316 | amplitude *= this._persistance; 317 | max += amplitude; 318 | } 319 | 320 | const redistributed = Math.pow(result, this._redistribution); 321 | return redistributed / max; 322 | } 323 | } 324 | 325 | export { FBM, Perlin }; 326 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App"; 4 | 5 | ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /src/state/useSettings.ts: -------------------------------------------------------------------------------- 1 | import create from "zustand"; 2 | import { immer } from "zustand/middleware/immer"; 3 | 4 | export type SettingsState = { 5 | colors: { 6 | [key: string]: { 7 | value: number; 8 | color: string; 9 | }; 10 | }; 11 | display: "color" | "height"; 12 | generation: { 13 | Seed: number; 14 | Height: number; 15 | Scale: number; 16 | Detail: number; 17 | Fuzzyness: number; 18 | Resolution: number; 19 | }; 20 | }; 21 | 22 | export type SettingsActions = { 23 | setColorValue: (key: string, value: number) => void; 24 | setColor: (key: string, color: string) => void; 25 | setDisplay: (value: SettingsState["display"]) => void; 26 | setGeneration: (key: keyof SettingsState["generation"], value: number) => void; 27 | }; 28 | 29 | export type Settings = SettingsState & SettingsActions; 30 | 31 | const initialState: SettingsState = { 32 | colors: { 33 | Snow: { 34 | value: 0.6, 35 | color: "#9aa7ad" 36 | }, 37 | Stone: { 38 | value: 0.36, 39 | color: "#656565" 40 | }, 41 | Forest: { 42 | value: 0.29, 43 | color: "#586647" 44 | }, 45 | Shrub: { 46 | value: 0.1, 47 | color: "#9ea667" 48 | }, 49 | Beach: { 50 | value: 0.04, 51 | color: "#efb28f" 52 | }, 53 | Shore: { 54 | value: 0.01, 55 | color: "#ffd68f" 56 | }, 57 | Water: { 58 | value: 0.42, 59 | color: "#00a9ff" 60 | } 61 | }, 62 | display: "color", 63 | generation: { 64 | Seed: Math.random(), 65 | Height: 1, 66 | Scale: 0.3, 67 | Detail: 0.5, 68 | Fuzzyness: 0.2, 69 | Resolution: 0.3 70 | } 71 | }; 72 | 73 | export const useSettings = create( 74 | immer((set) => ({ 75 | ...initialState, 76 | setColorValue: (key, value) => 77 | set((state) => { 78 | state.colors[key].value = value; 79 | }), 80 | setColor: (key, color) => 81 | set((state) => { 82 | state.colors[key].color = color; 83 | }), 84 | setDisplay: (value) => 85 | set((state) => { 86 | state.display = value; 87 | }), 88 | setGeneration: (key, value) => 89 | set((state) => { 90 | state.generation[key] = value; 91 | }) 92 | })) 93 | ); 94 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | import { visualizer } from "rollup-plugin-visualizer"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), visualizer()] 8 | }); 9 | --------------------------------------------------------------------------------