1 /* 2 Copyright (c) 2018-2020 Rafał Ziemniewski 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 28 module dagon.graphics.opensimplex; 29 30 import std.traits; 31 32 import dlib.core.memory; 33 import dlib.core.ownership; 34 35 class OpenSimplexNoise(T): Owner if (isFloatingPoint!T) 36 { 37 enum T STRETCH_CONSTANT_2D = -0.211324865405187; //(1/Math.sqrt(2+1)-1)/2; 38 enum T SQUISH_CONSTANT_2D = 0.366025403784439; //(Math.sqrt(2+1)-1)/2; 39 enum T STRETCH_CONSTANT_3D = -1.0 / 6; //(1/Math.sqrt(3+1)-1)/3; 40 enum T SQUISH_CONSTANT_3D = 1.0 / 3; //(Math.sqrt(3+1)-1)/3; 41 enum T STRETCH_CONSTANT_4D = -0.138196601125011; //(1/Math.sqrt(4+1)-1)/4; 42 enum T SQUISH_CONSTANT_4D = 0.309016994374947; //(Math.sqrt(4+1)-1)/4; 43 44 enum T NORM_CONSTANT_2D = 47; 45 enum T NORM_CONSTANT_3D = 103; 46 enum T NORM_CONSTANT_4D = 30; 47 48 enum long DEFAULT_SEED = 0; 49 50 private short[] perm; 51 private short[] permGradIndex3D; 52 53 public this(Owner o) 54 { 55 this(DEFAULT_SEED, o); 56 } 57 58 /* 59 public this(short[] perm) 60 { 61 this.perm = perm; 62 permGradIndex3D = New!(short[])(256); 63 64 for (int i = 0; i < 256; i++) 65 { 66 //Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array. 67 permGradIndex3D[i] = cast(short)((perm[i] % (gradients3D.length / 3)) * 3); 68 } 69 } 70 */ 71 72 //Initializes the class using a permutation array generated from a 64-bit seed. 73 //Generates a proper permutation (i.e. doesn't merely perform N successive pair swaps on a base array) 74 //Uses a simple 64-bit LCG. 75 public this(long seed, Owner o) 76 { 77 super(o); 78 perm = New!(short[])(256); 79 permGradIndex3D = New!(short[])(256); 80 short[] source = New!(short[])(256); 81 for (short i = 0; i < 256; i++) 82 source[i] = i; 83 seed = seed * 6_364_136_223_846_793_005L + 1_442_695_040_888_963_407L; 84 seed = seed * 6_364_136_223_846_793_005L + 1_442_695_040_888_963_407L; 85 seed = seed * 6_364_136_223_846_793_005L + 1_442_695_040_888_963_407L; 86 for (int i = 255; i >= 0; i--) 87 { 88 seed = seed * 6_364_136_223_846_793_005L + 1_442_695_040_888_963_407L; 89 int r = cast(int)((seed + 31) % (i + 1)); 90 if (r < 0) 91 r += (i + 1); 92 perm[i] = source[r]; 93 permGradIndex3D[i] = cast(short)((perm[i] % (gradients3D.length / 3)) * 3); 94 source[r] = source[i]; 95 } 96 97 Delete(source); 98 } 99 100 public ~this() 101 { 102 Delete(perm); 103 Delete(permGradIndex3D); 104 } 105 106 //2D OpenSimplex (Simplectic) Noise. 107 public T eval(T x, T y) 108 { 109 //Place input coordinates onto grid. 110 T stretchOffset = (x + y) * STRETCH_CONSTANT_2D; 111 T xs = x + stretchOffset; 112 T ys = y + stretchOffset; 113 114 //Floor to get grid coordinates of rhombus (stretched square) super-cell origin. 115 int xsb = fastFloor(xs); 116 int ysb = fastFloor(ys); 117 118 //Skew out to get actual coordinates of rhombus origin. We'll need these later. 119 T squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D; 120 T xb = xsb + squishOffset; 121 T yb = ysb + squishOffset; 122 123 //Compute grid coordinates relative to rhombus origin. 124 T xins = xs - xsb; 125 T yins = ys - ysb; 126 127 //Sum those together to get a value that determines which region we're in. 128 T inSum = xins + yins; 129 130 //Positions relative to origin point. 131 T dx0 = x - xb; 132 T dy0 = y - yb; 133 134 //We'll be defining these inside the next block and using them afterwards. 135 T dx_ext, dy_ext; 136 int xsv_ext, ysv_ext; 137 138 T value = 0; 139 140 //Contribution (1,0) 141 T dx1 = dx0 - 1 - SQUISH_CONSTANT_2D; 142 T dy1 = dy0 - 0 - SQUISH_CONSTANT_2D; 143 T attn1 = 2 - dx1 * dx1 - dy1 * dy1; 144 if (attn1 > 0) { 145 attn1 *= attn1; 146 value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, dx1, dy1); 147 } 148 149 //Contribution (0,1) 150 T dx2 = dx0 - 0 - SQUISH_CONSTANT_2D; 151 T dy2 = dy0 - 1 - SQUISH_CONSTANT_2D; 152 T attn2 = 2 - dx2 * dx2 - dy2 * dy2; 153 if (attn2 > 0) { 154 attn2 *= attn2; 155 value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, dx2, dy2); 156 } 157 158 if (inSum <= 1) { //We're inside the triangle (2-Simplex) at (0,0) 159 T zins = 1 - inSum; 160 if (zins > xins || zins > yins) { //(0,0) is one of the closest two triangular vertices 161 if (xins > yins) { 162 xsv_ext = xsb + 1; 163 ysv_ext = ysb - 1; 164 dx_ext = dx0 - 1; 165 dy_ext = dy0 + 1; 166 } else { 167 xsv_ext = xsb - 1; 168 ysv_ext = ysb + 1; 169 dx_ext = dx0 + 1; 170 dy_ext = dy0 - 1; 171 } 172 } else { //(1,0) and (0,1) are the closest two vertices. 173 xsv_ext = xsb + 1; 174 ysv_ext = ysb + 1; 175 dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; 176 dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; 177 } 178 } else { //We're inside the triangle (2-Simplex) at (1,1) 179 T zins = 2 - inSum; 180 if (zins < xins || zins < yins) { //(0,0) is one of the closest two triangular vertices 181 if (xins > yins) { 182 xsv_ext = xsb + 2; 183 ysv_ext = ysb + 0; 184 dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D; 185 dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D; 186 } else { 187 xsv_ext = xsb + 0; 188 ysv_ext = ysb + 2; 189 dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D; 190 dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D; 191 } 192 } else { //(1,0) and (0,1) are the closest two vertices. 193 dx_ext = dx0; 194 dy_ext = dy0; 195 xsv_ext = xsb; 196 ysv_ext = ysb; 197 } 198 xsb += 1; 199 ysb += 1; 200 dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D; 201 dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D; 202 } 203 204 //Contribution (0,0) or (1,1) 205 T attn0 = 2 - dx0 * dx0 - dy0 * dy0; 206 if (attn0 > 0) { 207 attn0 *= attn0; 208 value += attn0 * attn0 * extrapolate(xsb, ysb, dx0, dy0); 209 } 210 211 //Extra Vertex 212 T attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext; 213 if (attn_ext > 0) { 214 attn_ext *= attn_ext; 215 value += attn_ext * attn_ext * extrapolate(xsv_ext, ysv_ext, dx_ext, dy_ext); 216 } 217 218 return value / NORM_CONSTANT_2D; 219 } 220 221 //3D OpenSimplex (Simplectic) Noise. 222 public T eval(T x, T y, T z) { 223 224 //Place input coordinates on simplectic honeycomb. 225 T stretchOffset = (x + y + z) * STRETCH_CONSTANT_3D; 226 T xs = x + stretchOffset; 227 T ys = y + stretchOffset; 228 T zs = z + stretchOffset; 229 230 //Floor to get simplectic honeycomb coordinates of rhombohedron (stretched cube) super-cell origin. 231 int xsb = fastFloor(xs); 232 int ysb = fastFloor(ys); 233 int zsb = fastFloor(zs); 234 235 //Skew out to get actual coordinates of rhombohedron origin. We'll need these later. 236 T squishOffset = (xsb + ysb + zsb) * SQUISH_CONSTANT_3D; 237 T xb = xsb + squishOffset; 238 T yb = ysb + squishOffset; 239 T zb = zsb + squishOffset; 240 241 //Compute simplectic honeycomb coordinates relative to rhombohedral origin. 242 T xins = xs - xsb; 243 T yins = ys - ysb; 244 T zins = zs - zsb; 245 246 //Sum those together to get a value that determines which region we're in. 247 T inSum = xins + yins + zins; 248 249 //Positions relative to origin point. 250 T dx0 = x - xb; 251 T dy0 = y - yb; 252 T dz0 = z - zb; 253 254 //We'll be defining these inside the next block and using them afterwards. 255 T dx_ext0, dy_ext0, dz_ext0; 256 T dx_ext1, dy_ext1, dz_ext1; 257 int xsv_ext0, ysv_ext0, zsv_ext0; 258 int xsv_ext1, ysv_ext1, zsv_ext1; 259 260 T value = 0; 261 if (inSum <= 1) { //We're inside the tetrahedron (3-Simplex) at (0,0,0) 262 263 //Determine which two of (0,0,1), (0,1,0), (1,0,0) are closest. 264 byte aPoint = 0x01; 265 T aScore = xins; 266 byte bPoint = 0x02; 267 T bScore = yins; 268 if (aScore >= bScore && zins > bScore) { 269 bScore = zins; 270 bPoint = 0x04; 271 } else if (aScore < bScore && zins > aScore) { 272 aScore = zins; 273 aPoint = 0x04; 274 } 275 276 //Now we determine the two lattice points not part of the tetrahedron that may contribute. 277 //This depends on the closest two tetrahedral vertices, including (0,0,0) 278 T wins = 1 - inSum; 279 if (wins > aScore || wins > bScore) { //(0,0,0) is one of the closest two tetrahedral vertices. 280 byte c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. 281 282 if ((c & 0x01) == 0) { 283 xsv_ext0 = xsb - 1; 284 xsv_ext1 = xsb; 285 dx_ext0 = dx0 + 1; 286 dx_ext1 = dx0; 287 } else { 288 xsv_ext0 = xsv_ext1 = xsb + 1; 289 dx_ext0 = dx_ext1 = dx0 - 1; 290 } 291 292 if ((c & 0x02) == 0) { 293 ysv_ext0 = ysv_ext1 = ysb; 294 dy_ext0 = dy_ext1 = dy0; 295 if ((c & 0x01) == 0) { 296 ysv_ext1 -= 1; 297 dy_ext1 += 1; 298 } else { 299 ysv_ext0 -= 1; 300 dy_ext0 += 1; 301 } 302 } else { 303 ysv_ext0 = ysv_ext1 = ysb + 1; 304 dy_ext0 = dy_ext1 = dy0 - 1; 305 } 306 307 if ((c & 0x04) == 0) { 308 zsv_ext0 = zsb; 309 zsv_ext1 = zsb - 1; 310 dz_ext0 = dz0; 311 dz_ext1 = dz0 + 1; 312 } else { 313 zsv_ext0 = zsv_ext1 = zsb + 1; 314 dz_ext0 = dz_ext1 = dz0 - 1; 315 } 316 } else { //(0,0,0) is not one of the closest two tetrahedral vertices. 317 byte c = cast(byte)(aPoint | bPoint); //Our two extra vertices are determined by the closest two. 318 319 if ((c & 0x01) == 0) { 320 xsv_ext0 = xsb; 321 xsv_ext1 = xsb - 1; 322 dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_3D; 323 dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; 324 } else { 325 xsv_ext0 = xsv_ext1 = xsb + 1; 326 dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; 327 dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; 328 } 329 330 if ((c & 0x02) == 0) { 331 ysv_ext0 = ysb; 332 ysv_ext1 = ysb - 1; 333 dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_3D; 334 dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; 335 } else { 336 ysv_ext0 = ysv_ext1 = ysb + 1; 337 dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; 338 dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; 339 } 340 341 if ((c & 0x04) == 0) { 342 zsv_ext0 = zsb; 343 zsv_ext1 = zsb - 1; 344 dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_3D; 345 dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; 346 } else { 347 zsv_ext0 = zsv_ext1 = zsb + 1; 348 dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; 349 dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; 350 } 351 } 352 353 //Contribution (0,0,0) 354 T attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; 355 if (attn0 > 0) { 356 attn0 *= attn0; 357 value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, dx0, dy0, dz0); 358 } 359 360 //Contribution (1,0,0) 361 T dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; 362 T dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; 363 T dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; 364 T attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; 365 if (attn1 > 0) { 366 attn1 *= attn1; 367 value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); 368 } 369 370 //Contribution (0,1,0) 371 T dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; 372 T dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; 373 T dz2 = dz1; 374 T attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; 375 if (attn2 > 0) { 376 attn2 *= attn2; 377 value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); 378 } 379 380 //Contribution (0,0,1) 381 T dx3 = dx2; 382 T dy3 = dy1; 383 T dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; 384 T attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; 385 if (attn3 > 0) { 386 attn3 *= attn3; 387 value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); 388 } 389 } else if (inSum >= 2) { //We're inside the tetrahedron (3-Simplex) at (1,1,1) 390 391 //Determine which two tetrahedral vertices are the closest, out of (1,1,0), (1,0,1), (0,1,1) but not (1,1,1). 392 byte aPoint = 0x06; 393 T aScore = xins; 394 byte bPoint = 0x05; 395 T bScore = yins; 396 if (aScore <= bScore && zins < bScore) { 397 bScore = zins; 398 bPoint = 0x03; 399 } else if (aScore > bScore && zins < aScore) { 400 aScore = zins; 401 aPoint = 0x03; 402 } 403 404 //Now we determine the two lattice points not part of the tetrahedron that may contribute. 405 //This depends on the closest two tetrahedral vertices, including (1,1,1) 406 T wins = 3 - inSum; 407 if (wins < aScore || wins < bScore) { //(1,1,1) is one of the closest two tetrahedral vertices. 408 byte c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. 409 410 if ((c & 0x01) != 0) { 411 xsv_ext0 = xsb + 2; 412 xsv_ext1 = xsb + 1; 413 dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_3D; 414 dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; 415 } else { 416 xsv_ext0 = xsv_ext1 = xsb; 417 dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_3D; 418 } 419 420 if ((c & 0x02) != 0) { 421 ysv_ext0 = ysv_ext1 = ysb + 1; 422 dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; 423 if ((c & 0x01) != 0) { 424 ysv_ext1 += 1; 425 dy_ext1 -= 1; 426 } else { 427 ysv_ext0 += 1; 428 dy_ext0 -= 1; 429 } 430 } else { 431 ysv_ext0 = ysv_ext1 = ysb; 432 dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_3D; 433 } 434 435 if ((c & 0x04) != 0) { 436 zsv_ext0 = zsb + 1; 437 zsv_ext1 = zsb + 2; 438 dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; 439 dz_ext1 = dz0 - 2 - 3 * SQUISH_CONSTANT_3D; 440 } else { 441 zsv_ext0 = zsv_ext1 = zsb; 442 dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_3D; 443 } 444 } else { //(1,1,1) is not one of the closest two tetrahedral vertices. 445 byte c = cast(byte)(aPoint & bPoint); //Our two extra vertices are determined by the closest two. 446 447 if ((c & 0x01) != 0) { 448 xsv_ext0 = xsb + 1; 449 xsv_ext1 = xsb + 2; 450 dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; 451 dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; 452 } else { 453 xsv_ext0 = xsv_ext1 = xsb; 454 dx_ext0 = dx0 - SQUISH_CONSTANT_3D; 455 dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; 456 } 457 458 if ((c & 0x02) != 0) { 459 ysv_ext0 = ysb + 1; 460 ysv_ext1 = ysb + 2; 461 dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; 462 dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; 463 } else { 464 ysv_ext0 = ysv_ext1 = ysb; 465 dy_ext0 = dy0 - SQUISH_CONSTANT_3D; 466 dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; 467 } 468 469 if ((c & 0x04) != 0) { 470 zsv_ext0 = zsb + 1; 471 zsv_ext1 = zsb + 2; 472 dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; 473 dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; 474 } else { 475 zsv_ext0 = zsv_ext1 = zsb; 476 dz_ext0 = dz0 - SQUISH_CONSTANT_3D; 477 dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; 478 } 479 } 480 481 //Contribution (1,1,0) 482 T dx3 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; 483 T dy3 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; 484 T dz3 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; 485 T attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; 486 if (attn3 > 0) { 487 attn3 *= attn3; 488 value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx3, dy3, dz3); 489 } 490 491 //Contribution (1,0,1) 492 T dx2 = dx3; 493 T dy2 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; 494 T dz2 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; 495 T attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; 496 if (attn2 > 0) { 497 attn2 *= attn2; 498 value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx2, dy2, dz2); 499 } 500 501 //Contribution (0,1,1) 502 T dx1 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; 503 T dy1 = dy3; 504 T dz1 = dz2; 505 T attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; 506 if (attn1 > 0) { 507 attn1 *= attn1; 508 value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx1, dy1, dz1); 509 } 510 511 //Contribution (1,1,1) 512 dx0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; 513 dy0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; 514 dz0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; 515 T attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0; 516 if (attn0 > 0) { 517 attn0 *= attn0; 518 value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, dx0, dy0, dz0); 519 } 520 } else { //We're inside the octahedron (Rectified 3-Simplex) in between. 521 T aScore; 522 byte aPoint; 523 bool aIsFurtherSide; 524 T bScore; 525 byte bPoint; 526 bool bIsFurtherSide; 527 528 //Decide between point (0,0,1) and (1,1,0) as closest 529 T p1 = xins + yins; 530 if (p1 > 1) { 531 aScore = p1 - 1; 532 aPoint = 0x03; 533 aIsFurtherSide = true; 534 } else { 535 aScore = 1 - p1; 536 aPoint = 0x04; 537 aIsFurtherSide = false; 538 } 539 540 //Decide between point (0,1,0) and (1,0,1) as closest 541 T p2 = xins + zins; 542 if (p2 > 1) { 543 bScore = p2 - 1; 544 bPoint = 0x05; 545 bIsFurtherSide = true; 546 } else { 547 bScore = 1 - p2; 548 bPoint = 0x02; 549 bIsFurtherSide = false; 550 } 551 552 //The closest out of the two (1,0,0) and (0,1,1) will replace the furthest out of the two decided above, if closer. 553 T p3 = yins + zins; 554 if (p3 > 1) { 555 T score = p3 - 1; 556 if (aScore <= bScore && aScore < score) { 557 aScore = score; 558 aPoint = 0x06; 559 aIsFurtherSide = true; 560 } else if (aScore > bScore && bScore < score) { 561 bScore = score; 562 bPoint = 0x06; 563 bIsFurtherSide = true; 564 } 565 } else { 566 T score = 1 - p3; 567 if (aScore <= bScore && aScore < score) { 568 aScore = score; 569 aPoint = 0x01; 570 aIsFurtherSide = false; 571 } else if (aScore > bScore && bScore < score) { 572 bScore = score; 573 bPoint = 0x01; 574 bIsFurtherSide = false; 575 } 576 } 577 578 //Where each of the two closest points are determines how the extra two vertices are calculated. 579 if (aIsFurtherSide == bIsFurtherSide) { 580 if (aIsFurtherSide) { //Both closest points on (1,1,1) side 581 582 //One of the two extra points is (1,1,1) 583 dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D; 584 dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D; 585 dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D; 586 xsv_ext0 = xsb + 1; 587 ysv_ext0 = ysb + 1; 588 zsv_ext0 = zsb + 1; 589 590 //Other extra point is based on the shared axis. 591 byte c = cast(byte)(aPoint & bPoint); 592 if ((c & 0x01) != 0) { 593 dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D; 594 dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; 595 dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; 596 xsv_ext1 = xsb + 2; 597 ysv_ext1 = ysb; 598 zsv_ext1 = zsb; 599 } else if ((c & 0x02) != 0) { 600 dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; 601 dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D; 602 dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; 603 xsv_ext1 = xsb; 604 ysv_ext1 = ysb + 2; 605 zsv_ext1 = zsb; 606 } else { 607 dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; 608 dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; 609 dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D; 610 xsv_ext1 = xsb; 611 ysv_ext1 = ysb; 612 zsv_ext1 = zsb + 2; 613 } 614 } else {//Both closest points on (0,0,0) side 615 616 //One of the two extra points is (0,0,0) 617 dx_ext0 = dx0; 618 dy_ext0 = dy0; 619 dz_ext0 = dz0; 620 xsv_ext0 = xsb; 621 ysv_ext0 = ysb; 622 zsv_ext0 = zsb; 623 624 //Other extra point is based on the omitted axis. 625 byte c = cast(byte)(aPoint | bPoint); 626 if ((c & 0x01) == 0) { 627 dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D; 628 dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; 629 dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; 630 xsv_ext1 = xsb - 1; 631 ysv_ext1 = ysb + 1; 632 zsv_ext1 = zsb + 1; 633 } else if ((c & 0x02) == 0) { 634 dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; 635 dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D; 636 dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D; 637 xsv_ext1 = xsb + 1; 638 ysv_ext1 = ysb - 1; 639 zsv_ext1 = zsb + 1; 640 } else { 641 dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D; 642 dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D; 643 dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D; 644 xsv_ext1 = xsb + 1; 645 ysv_ext1 = ysb + 1; 646 zsv_ext1 = zsb - 1; 647 } 648 } 649 } else { //One point on (0,0,0) side, one point on (1,1,1) side 650 byte c1, c2; 651 if (aIsFurtherSide) { 652 c1 = aPoint; 653 c2 = bPoint; 654 } else { 655 c1 = bPoint; 656 c2 = aPoint; 657 } 658 659 //One contribution is a permutation of (1,1,-1) 660 if ((c1 & 0x01) == 0) { 661 dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_3D; 662 dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; 663 dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; 664 xsv_ext0 = xsb - 1; 665 ysv_ext0 = ysb + 1; 666 zsv_ext0 = zsb + 1; 667 } else if ((c1 & 0x02) == 0) { 668 dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; 669 dy_ext0 = dy0 + 1 - SQUISH_CONSTANT_3D; 670 dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D; 671 xsv_ext0 = xsb + 1; 672 ysv_ext0 = ysb - 1; 673 zsv_ext0 = zsb + 1; 674 } else { 675 dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D; 676 dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D; 677 dz_ext0 = dz0 + 1 - SQUISH_CONSTANT_3D; 678 xsv_ext0 = xsb + 1; 679 ysv_ext0 = ysb + 1; 680 zsv_ext0 = zsb - 1; 681 } 682 683 //One contribution is a permutation of (0,0,2) 684 dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D; 685 dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D; 686 dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D; 687 xsv_ext1 = xsb; 688 ysv_ext1 = ysb; 689 zsv_ext1 = zsb; 690 if ((c2 & 0x01) != 0) { 691 dx_ext1 -= 2; 692 xsv_ext1 += 2; 693 } else if ((c2 & 0x02) != 0) { 694 dy_ext1 -= 2; 695 ysv_ext1 += 2; 696 } else { 697 dz_ext1 -= 2; 698 zsv_ext1 += 2; 699 } 700 } 701 702 //Contribution (1,0,0) 703 T dx1 = dx0 - 1 - SQUISH_CONSTANT_3D; 704 T dy1 = dy0 - 0 - SQUISH_CONSTANT_3D; 705 T dz1 = dz0 - 0 - SQUISH_CONSTANT_3D; 706 T attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1; 707 if (attn1 > 0) { 708 attn1 *= attn1; 709 value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1); 710 } 711 712 //Contribution (0,1,0) 713 T dx2 = dx0 - 0 - SQUISH_CONSTANT_3D; 714 T dy2 = dy0 - 1 - SQUISH_CONSTANT_3D; 715 T dz2 = dz1; 716 T attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2; 717 if (attn2 > 0) { 718 attn2 *= attn2; 719 value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2); 720 } 721 722 //Contribution (0,0,1) 723 T dx3 = dx2; 724 T dy3 = dy1; 725 T dz3 = dz0 - 1 - SQUISH_CONSTANT_3D; 726 T attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3; 727 if (attn3 > 0) { 728 attn3 *= attn3; 729 value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3); 730 } 731 732 //Contribution (1,1,0) 733 T dx4 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D; 734 T dy4 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D; 735 T dz4 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D; 736 T attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4; 737 if (attn4 > 0) { 738 attn4 *= attn4; 739 value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 0, dx4, dy4, dz4); 740 } 741 742 //Contribution (1,0,1) 743 T dx5 = dx4; 744 T dy5 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D; 745 T dz5 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D; 746 T attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5; 747 if (attn5 > 0) { 748 attn5 *= attn5; 749 value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 0, zsb + 1, dx5, dy5, dz5); 750 } 751 752 //Contribution (0,1,1) 753 T dx6 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D; 754 T dy6 = dy4; 755 T dz6 = dz5; 756 T attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6; 757 if (attn6 > 0) { 758 attn6 *= attn6; 759 value += attn6 * attn6 * extrapolate(xsb + 0, ysb + 1, zsb + 1, dx6, dy6, dz6); 760 } 761 } 762 763 //First extra vertex 764 T attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0; 765 if (attn_ext0 > 0) 766 { 767 attn_ext0 *= attn_ext0; 768 value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, dx_ext0, dy_ext0, dz_ext0); 769 } 770 771 //Second extra vertex 772 T attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1; 773 if (attn_ext1 > 0) 774 { 775 attn_ext1 *= attn_ext1; 776 value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, dx_ext1, dy_ext1, dz_ext1); 777 } 778 779 return value / NORM_CONSTANT_3D; 780 } 781 782 //4D OpenSimplex (Simplectic) Noise. 783 public T eval(T x, T y, T z, T w) { 784 785 //Place input coordinates on simplectic honeycomb. 786 T stretchOffset = (x + y + z + w) * STRETCH_CONSTANT_4D; 787 T xs = x + stretchOffset; 788 T ys = y + stretchOffset; 789 T zs = z + stretchOffset; 790 T ws = w + stretchOffset; 791 792 //Floor to get simplectic honeycomb coordinates of rhombo-hypercube super-cell origin. 793 int xsb = fastFloor(xs); 794 int ysb = fastFloor(ys); 795 int zsb = fastFloor(zs); 796 int wsb = fastFloor(ws); 797 798 //Skew out to get actual coordinates of stretched rhombo-hypercube origin. We'll need these later. 799 T squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_CONSTANT_4D; 800 T xb = xsb + squishOffset; 801 T yb = ysb + squishOffset; 802 T zb = zsb + squishOffset; 803 T wb = wsb + squishOffset; 804 805 //Compute simplectic honeycomb coordinates relative to rhombo-hypercube origin. 806 T xins = xs - xsb; 807 T yins = ys - ysb; 808 T zins = zs - zsb; 809 T wins = ws - wsb; 810 811 //Sum those together to get a value that determines which region we're in. 812 T inSum = xins + yins + zins + wins; 813 814 //Positions relative to origin point. 815 T dx0 = x - xb; 816 T dy0 = y - yb; 817 T dz0 = z - zb; 818 T dw0 = w - wb; 819 820 //We'll be defining these inside the next block and using them afterwards. 821 T dx_ext0, dy_ext0, dz_ext0, dw_ext0; 822 T dx_ext1, dy_ext1, dz_ext1, dw_ext1; 823 T dx_ext2, dy_ext2, dz_ext2, dw_ext2; 824 int xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0; 825 int xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1; 826 int xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2; 827 828 T value = 0; 829 if (inSum <= 1) { //We're inside the pentachoron (4-Simplex) at (0,0,0,0) 830 831 //Determine which two of (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0) are closest. 832 byte aPoint = 0x01; 833 T aScore = xins; 834 byte bPoint = 0x02; 835 T bScore = yins; 836 if (aScore >= bScore && zins > bScore) { 837 bScore = zins; 838 bPoint = 0x04; 839 } else if (aScore < bScore && zins > aScore) { 840 aScore = zins; 841 aPoint = 0x04; 842 } 843 if (aScore >= bScore && wins > bScore) { 844 bScore = wins; 845 bPoint = 0x08; 846 } else if (aScore < bScore && wins > aScore) { 847 aScore = wins; 848 aPoint = 0x08; 849 } 850 851 //Now we determine the three lattice points not part of the pentachoron that may contribute. 852 //This depends on the closest two pentachoron vertices, including (0,0,0,0) 853 T uins = 1 - inSum; 854 if (uins > aScore || uins > bScore) { //(0,0,0,0) is one of the closest two pentachoron vertices. 855 byte c = (bScore > aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. 856 if ((c & 0x01) == 0) { 857 xsv_ext0 = xsb - 1; 858 xsv_ext1 = xsv_ext2 = xsb; 859 dx_ext0 = dx0 + 1; 860 dx_ext1 = dx_ext2 = dx0; 861 } else { 862 xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; 863 dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1; 864 } 865 866 if ((c & 0x02) == 0) { 867 ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; 868 dy_ext0 = dy_ext1 = dy_ext2 = dy0; 869 if ((c & 0x01) == 0x01) { 870 ysv_ext0 -= 1; 871 dy_ext0 += 1; 872 } else { 873 ysv_ext1 -= 1; 874 dy_ext1 += 1; 875 } 876 } else { 877 ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; 878 dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1; 879 } 880 881 if ((c & 0x04) == 0) { 882 zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; 883 dz_ext0 = dz_ext1 = dz_ext2 = dz0; 884 if ((c & 0x03) != 0) { 885 if ((c & 0x03) == 0x03) { 886 zsv_ext0 -= 1; 887 dz_ext0 += 1; 888 } else { 889 zsv_ext1 -= 1; 890 dz_ext1 += 1; 891 } 892 } else { 893 zsv_ext2 -= 1; 894 dz_ext2 += 1; 895 } 896 } else { 897 zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; 898 dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1; 899 } 900 901 if ((c & 0x08) == 0) { 902 wsv_ext0 = wsv_ext1 = wsb; 903 wsv_ext2 = wsb - 1; 904 dw_ext0 = dw_ext1 = dw0; 905 dw_ext2 = dw0 + 1; 906 } else { 907 wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; 908 dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1; 909 } 910 } else { //(0,0,0,0) is not one of the closest two pentachoron vertices. 911 byte c = cast(byte)(aPoint | bPoint); //Our three extra vertices are determined by the closest two. 912 913 if ((c & 0x01) == 0) { 914 xsv_ext0 = xsv_ext2 = xsb; 915 xsv_ext1 = xsb - 1; 916 dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; 917 dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_4D; 918 dx_ext2 = dx0 - SQUISH_CONSTANT_4D; 919 } else { 920 xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1; 921 dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 922 dx_ext1 = dx_ext2 = dx0 - 1 - SQUISH_CONSTANT_4D; 923 } 924 925 if ((c & 0x02) == 0) { 926 ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; 927 dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; 928 dy_ext1 = dy_ext2 = dy0 - SQUISH_CONSTANT_4D; 929 if ((c & 0x01) == 0x01) { 930 ysv_ext1 -= 1; 931 dy_ext1 += 1; 932 } else { 933 ysv_ext2 -= 1; 934 dy_ext2 += 1; 935 } 936 } else { 937 ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; 938 dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 939 dy_ext1 = dy_ext2 = dy0 - 1 - SQUISH_CONSTANT_4D; 940 } 941 942 if ((c & 0x04) == 0) { 943 zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; 944 dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; 945 dz_ext1 = dz_ext2 = dz0 - SQUISH_CONSTANT_4D; 946 if ((c & 0x03) == 0x03) { 947 zsv_ext1 -= 1; 948 dz_ext1 += 1; 949 } else { 950 zsv_ext2 -= 1; 951 dz_ext2 += 1; 952 } 953 } else { 954 zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; 955 dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 956 dz_ext1 = dz_ext2 = dz0 - 1 - SQUISH_CONSTANT_4D; 957 } 958 959 if ((c & 0x08) == 0) { 960 wsv_ext0 = wsv_ext1 = wsb; 961 wsv_ext2 = wsb - 1; 962 dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; 963 dw_ext1 = dw0 - SQUISH_CONSTANT_4D; 964 dw_ext2 = dw0 + 1 - SQUISH_CONSTANT_4D; 965 } else { 966 wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1; 967 dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 968 dw_ext1 = dw_ext2 = dw0 - 1 - SQUISH_CONSTANT_4D; 969 } 970 } 971 972 //Contribution (0,0,0,0) 973 T attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; 974 if (attn0 > 0) { 975 attn0 *= attn0; 976 value += attn0 * attn0 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 0, dx0, dy0, dz0, dw0); 977 } 978 979 //Contribution (1,0,0,0) 980 T dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; 981 T dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; 982 T dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; 983 T dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; 984 T attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; 985 if (attn1 > 0) { 986 attn1 *= attn1; 987 value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); 988 } 989 990 //Contribution (0,1,0,0) 991 T dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; 992 T dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; 993 T dz2 = dz1; 994 T dw2 = dw1; 995 T attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; 996 if (attn2 > 0) { 997 attn2 *= attn2; 998 value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); 999 } 1000 1001 //Contribution (0,0,1,0) 1002 T dx3 = dx2; 1003 T dy3 = dy1; 1004 T dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; 1005 T dw3 = dw1; 1006 T attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; 1007 if (attn3 > 0) { 1008 attn3 *= attn3; 1009 value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); 1010 } 1011 1012 //Contribution (0,0,0,1) 1013 T dx4 = dx2; 1014 T dy4 = dy1; 1015 T dz4 = dz1; 1016 T dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; 1017 T attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; 1018 if (attn4 > 0) { 1019 attn4 *= attn4; 1020 value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); 1021 } 1022 } else if (inSum >= 3) { //We're inside the pentachoron (4-Simplex) at (1,1,1,1) 1023 //Determine which two of (1,1,1,0), (1,1,0,1), (1,0,1,1), (0,1,1,1) are closest. 1024 byte aPoint = 0x0E; 1025 T aScore = xins; 1026 byte bPoint = 0x0D; 1027 T bScore = yins; 1028 if (aScore <= bScore && zins < bScore) { 1029 bScore = zins; 1030 bPoint = 0x0B; 1031 } else if (aScore > bScore && zins < aScore) { 1032 aScore = zins; 1033 aPoint = 0x0B; 1034 } 1035 if (aScore <= bScore && wins < bScore) { 1036 bScore = wins; 1037 bPoint = 0x07; 1038 } else if (aScore > bScore && wins < aScore) { 1039 aScore = wins; 1040 aPoint = 0x07; 1041 } 1042 1043 //Now we determine the three lattice points not part of the pentachoron that may contribute. 1044 //This depends on the closest two pentachoron vertices, including (0,0,0,0) 1045 T uins = 4 - inSum; 1046 if (uins < aScore || uins < bScore) { //(1,1,1,1) is one of the closest two pentachoron vertices. 1047 byte c = (bScore < aScore ? bPoint : aPoint); //Our other closest vertex is the closest out of a and b. 1048 1049 if ((c & 0x01) != 0) { 1050 xsv_ext0 = xsb + 2; 1051 xsv_ext1 = xsv_ext2 = xsb + 1; 1052 dx_ext0 = dx0 - 2 - 4 * SQUISH_CONSTANT_4D; 1053 dx_ext1 = dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; 1054 } else { 1055 xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; 1056 dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * SQUISH_CONSTANT_4D; 1057 } 1058 1059 if ((c & 0x02) != 0) { 1060 ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; 1061 dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; 1062 if ((c & 0x01) != 0) { 1063 ysv_ext1 += 1; 1064 dy_ext1 -= 1; 1065 } else { 1066 ysv_ext0 += 1; 1067 dy_ext0 -= 1; 1068 } 1069 } else { 1070 ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; 1071 dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * SQUISH_CONSTANT_4D; 1072 } 1073 1074 if ((c & 0x04) != 0) { 1075 zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; 1076 dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; 1077 if ((c & 0x03) != 0x03) { 1078 if ((c & 0x03) == 0) { 1079 zsv_ext0 += 1; 1080 dz_ext0 -= 1; 1081 } else { 1082 zsv_ext1 += 1; 1083 dz_ext1 -= 1; 1084 } 1085 } else { 1086 zsv_ext2 += 1; 1087 dz_ext2 -= 1; 1088 } 1089 } else { 1090 zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; 1091 dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * SQUISH_CONSTANT_4D; 1092 } 1093 1094 if ((c & 0x08) != 0) { 1095 wsv_ext0 = wsv_ext1 = wsb + 1; 1096 wsv_ext2 = wsb + 2; 1097 dw_ext0 = dw_ext1 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; 1098 dw_ext2 = dw0 - 2 - 4 * SQUISH_CONSTANT_4D; 1099 } else { 1100 wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; 1101 dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * SQUISH_CONSTANT_4D; 1102 } 1103 } else { //(1,1,1,1) is not one of the closest two pentachoron vertices. 1104 byte c = cast(byte)(aPoint & bPoint); //Our three extra vertices are determined by the closest two. 1105 1106 if ((c & 0x01) != 0) { 1107 xsv_ext0 = xsv_ext2 = xsb + 1; 1108 xsv_ext1 = xsb + 2; 1109 dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 1110 dx_ext1 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; 1111 dx_ext2 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; 1112 } else { 1113 xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb; 1114 dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D; 1115 dx_ext1 = dx_ext2 = dx0 - 3 * SQUISH_CONSTANT_4D; 1116 } 1117 1118 if ((c & 0x02) != 0) { 1119 ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1; 1120 dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 1121 dy_ext1 = dy_ext2 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; 1122 if ((c & 0x01) != 0) { 1123 ysv_ext2 += 1; 1124 dy_ext2 -= 1; 1125 } else { 1126 ysv_ext1 += 1; 1127 dy_ext1 -= 1; 1128 } 1129 } else { 1130 ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb; 1131 dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D; 1132 dy_ext1 = dy_ext2 = dy0 - 3 * SQUISH_CONSTANT_4D; 1133 } 1134 1135 if ((c & 0x04) != 0) { 1136 zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1; 1137 dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 1138 dz_ext1 = dz_ext2 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; 1139 if ((c & 0x03) != 0) { 1140 zsv_ext2 += 1; 1141 dz_ext2 -= 1; 1142 } else { 1143 zsv_ext1 += 1; 1144 dz_ext1 -= 1; 1145 } 1146 } else { 1147 zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb; 1148 dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D; 1149 dz_ext1 = dz_ext2 = dz0 - 3 * SQUISH_CONSTANT_4D; 1150 } 1151 1152 if ((c & 0x08) != 0) { 1153 wsv_ext0 = wsv_ext1 = wsb + 1; 1154 wsv_ext2 = wsb + 2; 1155 dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 1156 dw_ext1 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; 1157 dw_ext2 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; 1158 } else { 1159 wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb; 1160 dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D; 1161 dw_ext1 = dw_ext2 = dw0 - 3 * SQUISH_CONSTANT_4D; 1162 } 1163 } 1164 1165 //Contribution (1,1,1,0) 1166 T dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; 1167 T dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; 1168 T dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; 1169 T dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; 1170 T attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; 1171 if (attn4 > 0) { 1172 attn4 *= attn4; 1173 value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); 1174 } 1175 1176 //Contribution (1,1,0,1) 1177 T dx3 = dx4; 1178 T dy3 = dy4; 1179 T dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; 1180 T dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; 1181 T attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; 1182 if (attn3 > 0) { 1183 attn3 *= attn3; 1184 value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); 1185 } 1186 1187 //Contribution (1,0,1,1) 1188 T dx2 = dx4; 1189 T dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; 1190 T dz2 = dz4; 1191 T dw2 = dw3; 1192 T attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; 1193 if (attn2 > 0) { 1194 attn2 *= attn2; 1195 value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); 1196 } 1197 1198 //Contribution (0,1,1,1) 1199 T dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; 1200 T dz1 = dz4; 1201 T dy1 = dy4; 1202 T dw1 = dw3; 1203 T attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; 1204 if (attn1 > 0) { 1205 attn1 *= attn1; 1206 value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); 1207 } 1208 1209 //Contribution (1,1,1,1) 1210 dx0 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; 1211 dy0 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; 1212 dz0 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; 1213 dw0 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; 1214 T attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0; 1215 if (attn0 > 0) { 1216 attn0 *= attn0; 1217 value += attn0 * attn0 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 1, dx0, dy0, dz0, dw0); 1218 } 1219 } else if (inSum <= 2) { //We're inside the first dispentachoron (Rectified 4-Simplex) 1220 T aScore; 1221 byte aPoint; 1222 bool aIsBiggerSide = true; 1223 T bScore; 1224 byte bPoint; 1225 bool bIsBiggerSide = true; 1226 1227 //Decide between (1,1,0,0) and (0,0,1,1) 1228 if (xins + yins > zins + wins) { 1229 aScore = xins + yins; 1230 aPoint = 0x03; 1231 } else { 1232 aScore = zins + wins; 1233 aPoint = 0x0C; 1234 } 1235 1236 //Decide between (1,0,1,0) and (0,1,0,1) 1237 if (xins + zins > yins + wins) { 1238 bScore = xins + zins; 1239 bPoint = 0x05; 1240 } else { 1241 bScore = yins + wins; 1242 bPoint = 0x0A; 1243 } 1244 1245 //Closer between (1,0,0,1) and (0,1,1,0) will replace the further of a and b, if closer. 1246 if (xins + wins > yins + zins) { 1247 T score = xins + wins; 1248 if (aScore >= bScore && score > bScore) { 1249 bScore = score; 1250 bPoint = 0x09; 1251 } else if (aScore < bScore && score > aScore) { 1252 aScore = score; 1253 aPoint = 0x09; 1254 } 1255 } else { 1256 T score = yins + zins; 1257 if (aScore >= bScore && score > bScore) { 1258 bScore = score; 1259 bPoint = 0x06; 1260 } else if (aScore < bScore && score > aScore) { 1261 aScore = score; 1262 aPoint = 0x06; 1263 } 1264 } 1265 1266 //Decide if (1,0,0,0) is closer. 1267 T p1 = 2 - inSum + xins; 1268 if (aScore >= bScore && p1 > bScore) { 1269 bScore = p1; 1270 bPoint = 0x01; 1271 bIsBiggerSide = false; 1272 } else if (aScore < bScore && p1 > aScore) { 1273 aScore = p1; 1274 aPoint = 0x01; 1275 aIsBiggerSide = false; 1276 } 1277 1278 //Decide if (0,1,0,0) is closer. 1279 T p2 = 2 - inSum + yins; 1280 if (aScore >= bScore && p2 > bScore) { 1281 bScore = p2; 1282 bPoint = 0x02; 1283 bIsBiggerSide = false; 1284 } else if (aScore < bScore && p2 > aScore) { 1285 aScore = p2; 1286 aPoint = 0x02; 1287 aIsBiggerSide = false; 1288 } 1289 1290 //Decide if (0,0,1,0) is closer. 1291 T p3 = 2 - inSum + zins; 1292 if (aScore >= bScore && p3 > bScore) { 1293 bScore = p3; 1294 bPoint = 0x04; 1295 bIsBiggerSide = false; 1296 } else if (aScore < bScore && p3 > aScore) { 1297 aScore = p3; 1298 aPoint = 0x04; 1299 aIsBiggerSide = false; 1300 } 1301 1302 //Decide if (0,0,0,1) is closer. 1303 T p4 = 2 - inSum + wins; 1304 if (aScore >= bScore && p4 > bScore) { 1305 bScore = p4; 1306 bPoint = 0x08; 1307 bIsBiggerSide = false; 1308 } else if (aScore < bScore && p4 > aScore) { 1309 aScore = p4; 1310 aPoint = 0x08; 1311 aIsBiggerSide = false; 1312 } 1313 1314 //Where each of the two closest points are determines how the extra three vertices are calculated. 1315 if (aIsBiggerSide == bIsBiggerSide) { 1316 if (aIsBiggerSide) { //Both closest points on the bigger side 1317 byte c1 = cast(byte)(aPoint | bPoint); 1318 byte c2 = cast(byte)(aPoint & bPoint); 1319 if ((c1 & 0x01) == 0) { 1320 xsv_ext0 = xsb; 1321 xsv_ext1 = xsb - 1; 1322 dx_ext0 = dx0 - 3 * SQUISH_CONSTANT_4D; 1323 dx_ext1 = dx0 + 1 - 2 * SQUISH_CONSTANT_4D; 1324 } else { 1325 xsv_ext0 = xsv_ext1 = xsb + 1; 1326 dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; 1327 dx_ext1 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 1328 } 1329 1330 if ((c1 & 0x02) == 0) { 1331 ysv_ext0 = ysb; 1332 ysv_ext1 = ysb - 1; 1333 dy_ext0 = dy0 - 3 * SQUISH_CONSTANT_4D; 1334 dy_ext1 = dy0 + 1 - 2 * SQUISH_CONSTANT_4D; 1335 } else { 1336 ysv_ext0 = ysv_ext1 = ysb + 1; 1337 dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; 1338 dy_ext1 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 1339 } 1340 1341 if ((c1 & 0x04) == 0) { 1342 zsv_ext0 = zsb; 1343 zsv_ext1 = zsb - 1; 1344 dz_ext0 = dz0 - 3 * SQUISH_CONSTANT_4D; 1345 dz_ext1 = dz0 + 1 - 2 * SQUISH_CONSTANT_4D; 1346 } else { 1347 zsv_ext0 = zsv_ext1 = zsb + 1; 1348 dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; 1349 dz_ext1 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 1350 } 1351 1352 if ((c1 & 0x08) == 0) { 1353 wsv_ext0 = wsb; 1354 wsv_ext1 = wsb - 1; 1355 dw_ext0 = dw0 - 3 * SQUISH_CONSTANT_4D; 1356 dw_ext1 = dw0 + 1 - 2 * SQUISH_CONSTANT_4D; 1357 } else { 1358 wsv_ext0 = wsv_ext1 = wsb + 1; 1359 dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; 1360 dw_ext1 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 1361 } 1362 1363 //One combination is a permutation of (0,0,0,2) based on c2 1364 xsv_ext2 = xsb; 1365 ysv_ext2 = ysb; 1366 zsv_ext2 = zsb; 1367 wsv_ext2 = wsb; 1368 dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; 1369 dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; 1370 dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; 1371 dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; 1372 if ((c2 & 0x01) != 0) { 1373 xsv_ext2 += 2; 1374 dx_ext2 -= 2; 1375 } else if ((c2 & 0x02) != 0) { 1376 ysv_ext2 += 2; 1377 dy_ext2 -= 2; 1378 } else if ((c2 & 0x04) != 0) { 1379 zsv_ext2 += 2; 1380 dz_ext2 -= 2; 1381 } else { 1382 wsv_ext2 += 2; 1383 dw_ext2 -= 2; 1384 } 1385 1386 } else { //Both closest points on the smaller side 1387 //One of the two extra points is (0,0,0,0) 1388 xsv_ext2 = xsb; 1389 ysv_ext2 = ysb; 1390 zsv_ext2 = zsb; 1391 wsv_ext2 = wsb; 1392 dx_ext2 = dx0; 1393 dy_ext2 = dy0; 1394 dz_ext2 = dz0; 1395 dw_ext2 = dw0; 1396 1397 //Other two points are based on the omitted axes. 1398 byte c = cast(byte)(aPoint | bPoint); 1399 1400 if ((c & 0x01) == 0) { 1401 xsv_ext0 = xsb - 1; 1402 xsv_ext1 = xsb; 1403 dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; 1404 dx_ext1 = dx0 - SQUISH_CONSTANT_4D; 1405 } else { 1406 xsv_ext0 = xsv_ext1 = xsb + 1; 1407 dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; 1408 } 1409 1410 if ((c & 0x02) == 0) { 1411 ysv_ext0 = ysv_ext1 = ysb; 1412 dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; 1413 if ((c & 0x01) == 0x01) 1414 { 1415 ysv_ext0 -= 1; 1416 dy_ext0 += 1; 1417 } else { 1418 ysv_ext1 -= 1; 1419 dy_ext1 += 1; 1420 } 1421 } else { 1422 ysv_ext0 = ysv_ext1 = ysb + 1; 1423 dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; 1424 } 1425 1426 if ((c & 0x04) == 0) { 1427 zsv_ext0 = zsv_ext1 = zsb; 1428 dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; 1429 if ((c & 0x03) == 0x03) 1430 { 1431 zsv_ext0 -= 1; 1432 dz_ext0 += 1; 1433 } else { 1434 zsv_ext1 -= 1; 1435 dz_ext1 += 1; 1436 } 1437 } else { 1438 zsv_ext0 = zsv_ext1 = zsb + 1; 1439 dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; 1440 } 1441 1442 if ((c & 0x08) == 0) 1443 { 1444 wsv_ext0 = wsb; 1445 wsv_ext1 = wsb - 1; 1446 dw_ext0 = dw0 - SQUISH_CONSTANT_4D; 1447 dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; 1448 } else { 1449 wsv_ext0 = wsv_ext1 = wsb + 1; 1450 dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; 1451 } 1452 1453 } 1454 } else { //One point on each "side" 1455 byte c1, c2; 1456 if (aIsBiggerSide) { 1457 c1 = aPoint; 1458 c2 = bPoint; 1459 } else { 1460 c1 = bPoint; 1461 c2 = aPoint; 1462 } 1463 1464 //Two contributions are the bigger-sided point with each 0 replaced with -1. 1465 if ((c1 & 0x01) == 0) { 1466 xsv_ext0 = xsb - 1; 1467 xsv_ext1 = xsb; 1468 dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D; 1469 dx_ext1 = dx0 - SQUISH_CONSTANT_4D; 1470 } else { 1471 xsv_ext0 = xsv_ext1 = xsb + 1; 1472 dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D; 1473 } 1474 1475 if ((c1 & 0x02) == 0) { 1476 ysv_ext0 = ysv_ext1 = ysb; 1477 dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D; 1478 if ((c1 & 0x01) == 0x01) { 1479 ysv_ext0 -= 1; 1480 dy_ext0 += 1; 1481 } else { 1482 ysv_ext1 -= 1; 1483 dy_ext1 += 1; 1484 } 1485 } else { 1486 ysv_ext0 = ysv_ext1 = ysb + 1; 1487 dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D; 1488 } 1489 1490 if ((c1 & 0x04) == 0) { 1491 zsv_ext0 = zsv_ext1 = zsb; 1492 dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D; 1493 if ((c1 & 0x03) == 0x03) { 1494 zsv_ext0 -= 1; 1495 dz_ext0 += 1; 1496 } else { 1497 zsv_ext1 -= 1; 1498 dz_ext1 += 1; 1499 } 1500 } else { 1501 zsv_ext0 = zsv_ext1 = zsb + 1; 1502 dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D; 1503 } 1504 1505 if ((c1 & 0x08) == 0) { 1506 wsv_ext0 = wsb; 1507 wsv_ext1 = wsb - 1; 1508 dw_ext0 = dw0 - SQUISH_CONSTANT_4D; 1509 dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D; 1510 } else { 1511 wsv_ext0 = wsv_ext1 = wsb + 1; 1512 dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D; 1513 } 1514 1515 //One contribution is a permutation of (0,0,0,2) based on the smaller-sided point 1516 xsv_ext2 = xsb; 1517 ysv_ext2 = ysb; 1518 zsv_ext2 = zsb; 1519 wsv_ext2 = wsb; 1520 dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D; 1521 dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D; 1522 dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D; 1523 dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D; 1524 if ((c2 & 0x01) != 0) { 1525 xsv_ext2 += 2; 1526 dx_ext2 -= 2; 1527 } else if ((c2 & 0x02) != 0) { 1528 ysv_ext2 += 2; 1529 dy_ext2 -= 2; 1530 } else if ((c2 & 0x04) != 0) { 1531 zsv_ext2 += 2; 1532 dz_ext2 -= 2; 1533 } else { 1534 wsv_ext2 += 2; 1535 dw_ext2 -= 2; 1536 } 1537 } 1538 1539 //Contribution (1,0,0,0) 1540 T dx1 = dx0 - 1 - SQUISH_CONSTANT_4D; 1541 T dy1 = dy0 - 0 - SQUISH_CONSTANT_4D; 1542 T dz1 = dz0 - 0 - SQUISH_CONSTANT_4D; 1543 T dw1 = dw0 - 0 - SQUISH_CONSTANT_4D; 1544 T attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; 1545 if (attn1 > 0) { 1546 attn1 *= attn1; 1547 value += attn1 * attn1 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1); 1548 } 1549 1550 //Contribution (0,1,0,0) 1551 T dx2 = dx0 - 0 - SQUISH_CONSTANT_4D; 1552 T dy2 = dy0 - 1 - SQUISH_CONSTANT_4D; 1553 T dz2 = dz1; 1554 T dw2 = dw1; 1555 T attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; 1556 if (attn2 > 0) { 1557 attn2 *= attn2; 1558 value += attn2 * attn2 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2); 1559 } 1560 1561 //Contribution (0,0,1,0) 1562 T dx3 = dx2; 1563 T dy3 = dy1; 1564 T dz3 = dz0 - 1 - SQUISH_CONSTANT_4D; 1565 T dw3 = dw1; 1566 T attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; 1567 if (attn3 > 0) { 1568 attn3 *= attn3; 1569 value += attn3 * attn3 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3); 1570 } 1571 1572 //Contribution (0,0,0,1) 1573 T dx4 = dx2; 1574 T dy4 = dy1; 1575 T dz4 = dz1; 1576 T dw4 = dw0 - 1 - SQUISH_CONSTANT_4D; 1577 T attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; 1578 if (attn4 > 0) { 1579 attn4 *= attn4; 1580 value += attn4 * attn4 * extrapolate(xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4); 1581 } 1582 1583 //Contribution (1,1,0,0) 1584 T dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 1585 T dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 1586 T dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; 1587 T dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; 1588 T attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; 1589 if (attn5 > 0) { 1590 attn5 *= attn5; 1591 value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); 1592 } 1593 1594 //Contribution (1,0,1,0) 1595 T dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 1596 T dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; 1597 T dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 1598 T dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; 1599 T attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; 1600 if (attn6 > 0) { 1601 attn6 *= attn6; 1602 value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); 1603 } 1604 1605 //Contribution (1,0,0,1) 1606 T dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 1607 T dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; 1608 T dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; 1609 T dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 1610 T attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; 1611 if (attn7 > 0) { 1612 attn7 *= attn7; 1613 value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); 1614 } 1615 1616 //Contribution (0,1,1,0) 1617 T dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; 1618 T dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 1619 T dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 1620 T dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; 1621 T attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; 1622 if (attn8 > 0) { 1623 attn8 *= attn8; 1624 value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); 1625 } 1626 1627 //Contribution (0,1,0,1) 1628 T dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; 1629 T dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 1630 T dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; 1631 T dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 1632 T attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; 1633 if (attn9 > 0) { 1634 attn9 *= attn9; 1635 value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); 1636 } 1637 1638 //Contribution (0,0,1,1) 1639 T dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; 1640 T dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; 1641 T dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 1642 T dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 1643 T attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; 1644 if (attn10 > 0) { 1645 attn10 *= attn10; 1646 value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); 1647 } 1648 } else { //We're inside the second dispentachoron (Rectified 4-Simplex) 1649 T aScore; 1650 byte aPoint; 1651 bool aIsBiggerSide = true; 1652 T bScore; 1653 byte bPoint; 1654 bool bIsBiggerSide = true; 1655 1656 //Decide between (0,0,1,1) and (1,1,0,0) 1657 if (xins + yins < zins + wins) { 1658 aScore = xins + yins; 1659 aPoint = 0x0C; 1660 } else { 1661 aScore = zins + wins; 1662 aPoint = 0x03; 1663 } 1664 1665 //Decide between (0,1,0,1) and (1,0,1,0) 1666 if (xins + zins < yins + wins) { 1667 bScore = xins + zins; 1668 bPoint = 0x0A; 1669 } else { 1670 bScore = yins + wins; 1671 bPoint = 0x05; 1672 } 1673 1674 //Closer between (0,1,1,0) and (1,0,0,1) will replace the further of a and b, if closer. 1675 if (xins + wins < yins + zins) { 1676 T score = xins + wins; 1677 if (aScore <= bScore && score < bScore) { 1678 bScore = score; 1679 bPoint = 0x06; 1680 } else if (aScore > bScore && score < aScore) { 1681 aScore = score; 1682 aPoint = 0x06; 1683 } 1684 } else { 1685 T score = yins + zins; 1686 if (aScore <= bScore && score < bScore) { 1687 bScore = score; 1688 bPoint = 0x09; 1689 } else if (aScore > bScore && score < aScore) { 1690 aScore = score; 1691 aPoint = 0x09; 1692 } 1693 } 1694 1695 //Decide if (0,1,1,1) is closer. 1696 T p1 = 3 - inSum + xins; 1697 if (aScore <= bScore && p1 < bScore) { 1698 bScore = p1; 1699 bPoint = 0x0E; 1700 bIsBiggerSide = false; 1701 } else if (aScore > bScore && p1 < aScore) { 1702 aScore = p1; 1703 aPoint = 0x0E; 1704 aIsBiggerSide = false; 1705 } 1706 1707 //Decide if (1,0,1,1) is closer. 1708 T p2 = 3 - inSum + yins; 1709 if (aScore <= bScore && p2 < bScore) { 1710 bScore = p2; 1711 bPoint = 0x0D; 1712 bIsBiggerSide = false; 1713 } else if (aScore > bScore && p2 < aScore) { 1714 aScore = p2; 1715 aPoint = 0x0D; 1716 aIsBiggerSide = false; 1717 } 1718 1719 //Decide if (1,1,0,1) is closer. 1720 T p3 = 3 - inSum + zins; 1721 if (aScore <= bScore && p3 < bScore) { 1722 bScore = p3; 1723 bPoint = 0x0B; 1724 bIsBiggerSide = false; 1725 } else if (aScore > bScore && p3 < aScore) { 1726 aScore = p3; 1727 aPoint = 0x0B; 1728 aIsBiggerSide = false; 1729 } 1730 1731 //Decide if (1,1,1,0) is closer. 1732 T p4 = 3 - inSum + wins; 1733 if (aScore <= bScore && p4 < bScore) { 1734 bScore = p4; 1735 bPoint = 0x07; 1736 bIsBiggerSide = false; 1737 } else if (aScore > bScore && p4 < aScore) { 1738 aScore = p4; 1739 aPoint = 0x07; 1740 aIsBiggerSide = false; 1741 } 1742 1743 //Where each of the two closest points are determines how the extra three vertices are calculated. 1744 if (aIsBiggerSide == bIsBiggerSide) { 1745 if (aIsBiggerSide) { //Both closest points on the bigger side 1746 byte c1 = cast(byte)(aPoint & bPoint); 1747 byte c2 = cast(byte)(aPoint | bPoint); 1748 1749 //Two contributions are permutations of (0,0,0,1) and (0,0,0,2) based on c1 1750 xsv_ext0 = xsv_ext1 = xsb; 1751 ysv_ext0 = ysv_ext1 = ysb; 1752 zsv_ext0 = zsv_ext1 = zsb; 1753 wsv_ext0 = wsv_ext1 = wsb; 1754 dx_ext0 = dx0 - SQUISH_CONSTANT_4D; 1755 dy_ext0 = dy0 - SQUISH_CONSTANT_4D; 1756 dz_ext0 = dz0 - SQUISH_CONSTANT_4D; 1757 dw_ext0 = dw0 - SQUISH_CONSTANT_4D; 1758 dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_4D; 1759 dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_4D; 1760 dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_4D; 1761 dw_ext1 = dw0 - 2 * SQUISH_CONSTANT_4D; 1762 if ((c1 & 0x01) != 0) { 1763 xsv_ext0 += 1; 1764 dx_ext0 -= 1; 1765 xsv_ext1 += 2; 1766 dx_ext1 -= 2; 1767 } else if ((c1 & 0x02) != 0) { 1768 ysv_ext0 += 1; 1769 dy_ext0 -= 1; 1770 ysv_ext1 += 2; 1771 dy_ext1 -= 2; 1772 } else if ((c1 & 0x04) != 0) { 1773 zsv_ext0 += 1; 1774 dz_ext0 -= 1; 1775 zsv_ext1 += 2; 1776 dz_ext1 -= 2; 1777 } else { 1778 wsv_ext0 += 1; 1779 dw_ext0 -= 1; 1780 wsv_ext1 += 2; 1781 dw_ext1 -= 2; 1782 } 1783 1784 //One contribution is a permutation of (1,1,1,-1) based on c2 1785 xsv_ext2 = xsb + 1; 1786 ysv_ext2 = ysb + 1; 1787 zsv_ext2 = zsb + 1; 1788 wsv_ext2 = wsb + 1; 1789 dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 1790 dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 1791 dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 1792 dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 1793 if ((c2 & 0x01) == 0) { 1794 xsv_ext2 -= 2; 1795 dx_ext2 += 2; 1796 } else if ((c2 & 0x02) == 0) { 1797 ysv_ext2 -= 2; 1798 dy_ext2 += 2; 1799 } else if ((c2 & 0x04) == 0) { 1800 zsv_ext2 -= 2; 1801 dz_ext2 += 2; 1802 } else { 1803 wsv_ext2 -= 2; 1804 dw_ext2 += 2; 1805 } 1806 } else { //Both closest points on the smaller side 1807 //One of the two extra points is (1,1,1,1) 1808 xsv_ext2 = xsb + 1; 1809 ysv_ext2 = ysb + 1; 1810 zsv_ext2 = zsb + 1; 1811 wsv_ext2 = wsb + 1; 1812 dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D; 1813 dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D; 1814 dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D; 1815 dw_ext2 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D; 1816 1817 //Other two points are based on the shared axes. 1818 byte c = cast(byte)(aPoint & bPoint); 1819 1820 if ((c & 0x01) != 0) { 1821 xsv_ext0 = xsb + 2; 1822 xsv_ext1 = xsb + 1; 1823 dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; 1824 dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; 1825 } else { 1826 xsv_ext0 = xsv_ext1 = xsb; 1827 dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; 1828 } 1829 1830 if ((c & 0x02) != 0) { 1831 ysv_ext0 = ysv_ext1 = ysb + 1; 1832 dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; 1833 if ((c & 0x01) == 0) 1834 { 1835 ysv_ext0 += 1; 1836 dy_ext0 -= 1; 1837 } else { 1838 ysv_ext1 += 1; 1839 dy_ext1 -= 1; 1840 } 1841 } else { 1842 ysv_ext0 = ysv_ext1 = ysb; 1843 dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; 1844 } 1845 1846 if ((c & 0x04) != 0) { 1847 zsv_ext0 = zsv_ext1 = zsb + 1; 1848 dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; 1849 if ((c & 0x03) == 0) 1850 { 1851 zsv_ext0 += 1; 1852 dz_ext0 -= 1; 1853 } else { 1854 zsv_ext1 += 1; 1855 dz_ext1 -= 1; 1856 } 1857 } else { 1858 zsv_ext0 = zsv_ext1 = zsb; 1859 dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; 1860 } 1861 1862 if ((c & 0x08) != 0) 1863 { 1864 wsv_ext0 = wsb + 1; 1865 wsv_ext1 = wsb + 2; 1866 dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; 1867 dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; 1868 } else { 1869 wsv_ext0 = wsv_ext1 = wsb; 1870 dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; 1871 } 1872 } 1873 } else { //One point on each "side" 1874 byte c1, c2; 1875 if (aIsBiggerSide) { 1876 c1 = aPoint; 1877 c2 = bPoint; 1878 } else { 1879 c1 = bPoint; 1880 c2 = aPoint; 1881 } 1882 1883 //Two contributions are the bigger-sided point with each 1 replaced with 2. 1884 if ((c1 & 0x01) != 0) { 1885 xsv_ext0 = xsb + 2; 1886 xsv_ext1 = xsb + 1; 1887 dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D; 1888 dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; 1889 } else { 1890 xsv_ext0 = xsv_ext1 = xsb; 1891 dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D; 1892 } 1893 1894 if ((c1 & 0x02) != 0) { 1895 ysv_ext0 = ysv_ext1 = ysb + 1; 1896 dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; 1897 if ((c1 & 0x01) == 0) { 1898 ysv_ext0 += 1; 1899 dy_ext0 -= 1; 1900 } else { 1901 ysv_ext1 += 1; 1902 dy_ext1 -= 1; 1903 } 1904 } else { 1905 ysv_ext0 = ysv_ext1 = ysb; 1906 dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D; 1907 } 1908 1909 if ((c1 & 0x04) != 0) { 1910 zsv_ext0 = zsv_ext1 = zsb + 1; 1911 dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; 1912 if ((c1 & 0x03) == 0) { 1913 zsv_ext0 += 1; 1914 dz_ext0 -= 1; 1915 } else { 1916 zsv_ext1 += 1; 1917 dz_ext1 -= 1; 1918 } 1919 } else { 1920 zsv_ext0 = zsv_ext1 = zsb; 1921 dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D; 1922 } 1923 1924 if ((c1 & 0x08) != 0) { 1925 wsv_ext0 = wsb + 1; 1926 wsv_ext1 = wsb + 2; 1927 dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; 1928 dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D; 1929 } else { 1930 wsv_ext0 = wsv_ext1 = wsb; 1931 dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D; 1932 } 1933 1934 //One contribution is a permutation of (1,1,1,-1) based on the smaller-sided point 1935 xsv_ext2 = xsb + 1; 1936 ysv_ext2 = ysb + 1; 1937 zsv_ext2 = zsb + 1; 1938 wsv_ext2 = wsb + 1; 1939 dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 1940 dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 1941 dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 1942 dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 1943 if ((c2 & 0x01) == 0) { 1944 xsv_ext2 -= 2; 1945 dx_ext2 += 2; 1946 } else if ((c2 & 0x02) == 0) { 1947 ysv_ext2 -= 2; 1948 dy_ext2 += 2; 1949 } else if ((c2 & 0x04) == 0) { 1950 zsv_ext2 -= 2; 1951 dz_ext2 += 2; 1952 } else { 1953 wsv_ext2 -= 2; 1954 dw_ext2 += 2; 1955 } 1956 } 1957 1958 //Contribution (1,1,1,0) 1959 T dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D; 1960 T dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D; 1961 T dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D; 1962 T dw4 = dw0 - 3 * SQUISH_CONSTANT_4D; 1963 T attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4; 1964 if (attn4 > 0) { 1965 attn4 *= attn4; 1966 value += attn4 * attn4 * extrapolate(xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4); 1967 } 1968 1969 //Contribution (1,1,0,1) 1970 T dx3 = dx4; 1971 T dy3 = dy4; 1972 T dz3 = dz0 - 3 * SQUISH_CONSTANT_4D; 1973 T dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D; 1974 T attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3; 1975 if (attn3 > 0) { 1976 attn3 *= attn3; 1977 value += attn3 * attn3 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3); 1978 } 1979 1980 //Contribution (1,0,1,1) 1981 T dx2 = dx4; 1982 T dy2 = dy0 - 3 * SQUISH_CONSTANT_4D; 1983 T dz2 = dz4; 1984 T dw2 = dw3; 1985 T attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2; 1986 if (attn2 > 0) { 1987 attn2 *= attn2; 1988 value += attn2 * attn2 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2); 1989 } 1990 1991 //Contribution (0,1,1,1) 1992 T dx1 = dx0 - 3 * SQUISH_CONSTANT_4D; 1993 T dz1 = dz4; 1994 T dy1 = dy4; 1995 T dw1 = dw3; 1996 T attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1; 1997 if (attn1 > 0) { 1998 attn1 *= attn1; 1999 value += attn1 * attn1 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1); 2000 } 2001 2002 //Contribution (1,1,0,0) 2003 T dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 2004 T dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 2005 T dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; 2006 T dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; 2007 T attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5; 2008 if (attn5 > 0) { 2009 attn5 *= attn5; 2010 value += attn5 * attn5 * extrapolate(xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5); 2011 } 2012 2013 //Contribution (1,0,1,0) 2014 T dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 2015 T dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; 2016 T dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 2017 T dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; 2018 T attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6; 2019 if (attn6 > 0) { 2020 attn6 *= attn6; 2021 value += attn6 * attn6 * extrapolate(xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6); 2022 } 2023 2024 //Contribution (1,0,0,1) 2025 T dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D; 2026 T dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; 2027 T dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; 2028 T dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 2029 T attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7; 2030 if (attn7 > 0) { 2031 attn7 *= attn7; 2032 value += attn7 * attn7 * extrapolate(xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7); 2033 } 2034 2035 //Contribution (0,1,1,0) 2036 T dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; 2037 T dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 2038 T dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 2039 T dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D; 2040 T attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8; 2041 if (attn8 > 0) { 2042 attn8 *= attn8; 2043 value += attn8 * attn8 * extrapolate(xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8); 2044 } 2045 2046 //Contribution (0,1,0,1) 2047 T dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; 2048 T dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D; 2049 T dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D; 2050 T dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 2051 T attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9; 2052 if (attn9 > 0) { 2053 attn9 *= attn9; 2054 value += attn9 * attn9 * extrapolate(xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9); 2055 } 2056 2057 //Contribution (0,0,1,1) 2058 T dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D; 2059 T dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D; 2060 T dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D; 2061 T dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D; 2062 T attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10; 2063 if (attn10 > 0) { 2064 attn10 *= attn10; 2065 value += attn10 * attn10 * extrapolate(xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10); 2066 } 2067 } 2068 2069 //First extra vertex 2070 T attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0; 2071 if (attn_ext0 > 0) 2072 { 2073 attn_ext0 *= attn_ext0; 2074 value += attn_ext0 * attn_ext0 * extrapolate(xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0, dx_ext0, dy_ext0, dz_ext0, dw_ext0); 2075 } 2076 2077 //Second extra vertex 2078 T attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1; 2079 if (attn_ext1 > 0) 2080 { 2081 attn_ext1 *= attn_ext1; 2082 value += attn_ext1 * attn_ext1 * extrapolate(xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1, dx_ext1, dy_ext1, dz_ext1, dw_ext1); 2083 } 2084 2085 //Third extra vertex 2086 T attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2; 2087 if (attn_ext2 > 0) 2088 { 2089 attn_ext2 *= attn_ext2; 2090 value += attn_ext2 * attn_ext2 * extrapolate(xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2, dx_ext2, dy_ext2, dz_ext2, dw_ext2); 2091 } 2092 2093 return value / NORM_CONSTANT_4D; 2094 } 2095 2096 private T extrapolate(int xsb, int ysb, T dx, T dy) 2097 { 2098 int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E; 2099 return gradients2D[index] * dx 2100 + gradients2D[index + 1] * dy; 2101 } 2102 2103 private T extrapolate(int xsb, int ysb, int zsb, T dx, T dy, T dz) 2104 { 2105 int index = permGradIndex3D[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF]; 2106 return gradients3D[index] * dx 2107 + gradients3D[index + 1] * dy 2108 + gradients3D[index + 2] * dz; 2109 } 2110 2111 private T extrapolate(int xsb, int ysb, int zsb, int wsb, T dx, T dy, T dz, T dw) 2112 { 2113 int index = perm[(perm[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF] + wsb) & 0xFF] & 0xFC; 2114 return gradients4D[index] * dx 2115 + gradients4D[index + 1] * dy 2116 + gradients4D[index + 2] * dz 2117 + gradients4D[index + 3] * dw; 2118 } 2119 2120 private static int fastFloor(T x) { 2121 int xi = cast(int)x; 2122 return x < xi ? xi - 1 : xi; 2123 } 2124 2125 //Gradients for 2D. They approximate the directions to the 2126 //vertices of an octagon from the center. 2127 private static immutable byte[] gradients2D = [ 2128 5, 2, 2, 5, 2129 -5, 2, -2, 5, 2130 5, -2, 2, -5, 2131 -5, -2, -2, -5, 2132 ]; 2133 2134 //Gradients for 3D. They approximate the directions to the 2135 //vertices of a rhombicuboctahedron from the center, skewed so 2136 //that the triangular and square facets can be inscribed inside 2137 //circles of the same radius. 2138 private static immutable byte[] gradients3D = [ 2139 -11, 4, 4, -4, 11, 4, -4, 4, 11, 2140 11, 4, 4, 4, 11, 4, 4, 4, 11, 2141 -11, -4, 4, -4, -11, 4, -4, -4, 11, 2142 11, -4, 4, 4, -11, 4, 4, -4, 11, 2143 -11, 4, -4, -4, 11, -4, -4, 4, -11, 2144 11, 4, -4, 4, 11, -4, 4, 4, -11, 2145 -11, -4, -4, -4, -11, -4, -4, -4, -11, 2146 11, -4, -4, 4, -11, -4, 4, -4, -11, 2147 ]; 2148 2149 //Gradients for 4D. They approximate the directions to the 2150 //vertices of a disprismatotesseractihexadecachoron from the center, 2151 //skewed so that the tetrahedral and cubic facets can be inscribed inside 2152 //spheres of the same radius. 2153 private static immutable byte[] gradients4D = [ 2154 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 2155 -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, 2156 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 2157 -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, 2158 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 2159 -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, 2160 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 2161 -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, 2162 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 2163 -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, 2164 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 2165 -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, 2166 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 2167 -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, 2168 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 2169 -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, 2170 ]; 2171 }