I've been implementing Improved Perlin Noise for a small library I'm writing. Everything was hunky dory when it was just in the 3rd dimension, but I recently expanded to the 1st, 2nd, and 4th dimension, which is where things started get weird.
I originally thought that the range of Improved Perlin was +-1.0. When I implemented the 1st dimension version, I noticed that the unmodified range was +-0.5, ie, you had to multiply the result by 2, but figured nothing of it. 2nd dimension worked just like 3rd, with both working within the +-1.0 range. Then when I got to 4th, I ran a large number of samples and saw that I was getting results outside the -1.0 to +1.0 range.
I started Googling, and apparently the +-1.0 range is a common misconception? The solution I've read in a couple places, which is +-1/2(sqrt(N)), where N is the number of dimensions, implies the following ranges for dimensions 1 through 4:
0.5, ~0.71, ~0.87, 1, respectively
However, the only version I have which matches this is the 1st dimension, which as I said, works out to +-0.5 before multiplying by 2. For dimensions 2 and 3, I get +-1.0 without any need to modify the result, and for the 4th dimension, I believe my results are actually in the range of the 6th dimension according to that solution.
The following is my code: https://pastebin.com/CpAi3PUF And for those who aren't familiar, it's Cython, so yes, a weird Frankenstein of Python and C.
I use the following code to test the ranges of each dimension: https://pastebin.com/yUpw1Z00 Since my method involves just running tons of random inputs over and over, I did run this test a few times to make sure the results are consistent, which they are, and here is an example of the output:
DIM1 - Minimum: -0.999999999999943 | Maximum: 0.9999999999871175 | Average: 0.0003455999808678627 DIM2 - Minimum: -0.9999515602331069 | Maximum: 0.999900249691747 | Average: -0.00011840974404335401 DIM3 - Minimum: -0.9932063986908607 | Maximum: 0.9931959744642007 | Average: -0.00010701170753012655 DIM4 - Minimum: -1.0576886515898196 | Maximum: 1.123720946368049 | Average: 0.00022555631399532482
You can clearly see that as my code is written, dimensions 1 through 3 have a limit of +1.0, and then with the 4So clearly there is some contradiction between the alleged result ranges, and the code I'm implementing. The 3rd and 4th dimensions were implemented straight from Perlin's own example code.
3rd Dimension: https://mrl.nyu.edu/~perlin/noise/
4th dimension: https://mrl.nyu.edu/~perlin/noise/ImprovedNoise4D.java
The only major changes I've made to the implementation are in the grad functions, where I use what is essentially a switch case, rather than Perlin's fancy pants (but extremely expensive) bitshifting method. But afaik doing so is functionally equivalent.
Can anyone provide some insight as to what is going on? What is causing the difference between the supposed expected ranges, and my actual results? And what can I do to get the 4th dimension "in shape", like how modifying the 1st dimension is required?
Thanks so much for any help.