## Fail attempt at Perlin noise algorithm

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
IcarusLives
Posts: 34
Joined: 17 Jan 2016 23:55

### Fail attempt at Perlin noise algorithm

Hello all,

I've been attempting to create the perlin noise algorithm. perlin noise algorithm

I really was hoping I could use this algorithm for some possible terrain generation for some sort of a game. I find the idea of perlin noise to be very interesting.

Upon my research I've learned that a piece of the algorithm consists of a smoothstep algorithm, which is given a value from a "clamp" function.

Here is my attempt at this code. I've only really gotten up to the smoothStep part, and implementing it into perlin noise is really challenging for me.

Only tested on Win10. Uses mshta javascript for floating point numbers

Code: Select all

``@echo off & setlocal enableDelayedExpansion        call :init:main   cls    for /l %%a in (0,9,99) do (        set /a "r=%%a"    REM for /l %%a in (1,1,10) do (        REM set /a "r=!random! %% %edge1% + %edge0%"                call :clamp x "(!r! - %edge0%)/(%edge1% - %edge0%)" 0.000 1.000        ::smoothstep(x) = 3x^2  - 2x^3        call :float_JS "smoothstep=!x! * !x! * ( 3 - 2 * !x!)"                echo !smoothstep!        REM call :genDisp !smoothstep:~2,1!    )pause & exit:genDisp    set "o="        if not "!smoothstep:~2,1!" equ "" (            for /l %%0 in (1,1,%1) do set "o=!o! "            echo !o!#        )goto :eof:prep_smoothStep    set /a "edge0=%1", "edge1=%2"goto :eof:clamp    call :float_JS "r=%~2"    if %r:~0,5% lss %3 ( set "%1=%3" ) else if %r:~0,5% gtr %4 ( set "%1=%4" ) else set "%1=%r:~0,5%"    set "r="goto :eof:float_JS    ( for /f "tokens=1,2 delims==" %%a in ("%~1") do (        for /f %%N in ('%beginJS% %%b %endJS%') do set "%%a=%%N"    ))goto :eof:init    set "beginJS=mshta "javascript:close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(eval("    set "endJS=)));""    call :prep_smoothStep 1 99goto :eof``

OUTPUT:

Code: Select all

``110.0794315660.173455750.2913484140.4222812160.5598720.6934000640.8135211520.9108910080.9761653761Press any key to continue . . .``

With all honesty, I believe I've done everything right so far, but something feels off to me. Opinions?
Last edited by IcarusLives on 02 Jan 2017 15:22, edited 5 times in total.

penpen
Expert
Posts: 1483
Joined: 23 Jun 2013 06:15
Location: Germany

### Re: Fail attempt at Perlin noise algorithm

On a first look your smoothstep implementation seems to be OK.

Note that when using this batch in multiple regions, the format of a floating point number may be unexpected:

Code: Select all

``1.234561,23456    ("if" won't work at all, because the comma character is a seperator.)+1.23456   (second "if" may fail, for example: if "+0.23400" gtr "1.00000" echo ok)1.235``
So you should enforce the number format you expect by yourself within :float_JS.

Your clamp should produce errors on negative numbers, because "batch if" cannot compare floating point numbers:

Code: Select all

``:: line: if %r:~0,7% lss %3 (:: this fails:if "-1.23400" lss "0.00000" echo ok``

penpen

IcarusLives
Posts: 34
Joined: 17 Jan 2016 23:55

### Re: Fail attempt at Perlin noise algorithm

penpen wrote:Your clamp should produce errors on negative numbers, because "batch if" cannot compare floating point numbers:

Code: Select all

``:: line: if %r:~0,7% lss %3 (:: this fails:if "-1.23400" lss "0.00000" echo ok``

penpen

I'm unsure about how this works on other OS's, but I'm running Win10. From what testing I have done. You must notice that there are an equ number of digits. I "believe" this works, because 'IF' will ignore the period if comparing gtr, geq, lss, or leq. Much like comparing the number as a whole number.

For example: 63.2 > 19.2 OR 632 > 192.

This is true in both situations, and the '.' is simply ignored.

Code: Select all

``>if 1.2 gtr 1.3 (echo yes) else (echo no)no>if 1.4 gtr 1.3 (echo yes) else (echo no)yes>if 63.4 gtr 99.0 (echo yes) else (echo no)no>if 63.4 gtr 19.0 (echo yes) else (echo no)yes>``

These below however will NOT work properly. You will notice that there were a different number of digits in each comparison.
NONE of these if statements below are correct

Code: Select all

``>if 63.2 lss 100.0 (echo yes) else (echo no)no>if 63.2 lss 9.0 (echo yes) else (echo no)yes>if 63.2 gtr 9.0 (echo yes) else (echo no)no>if 1.2 gtr 1.14 (echo yes) else (echo no)yes>``

penpen
Expert
Posts: 1483
Joined: 23 Jun 2013 06:15
Location: Germany

### Re: Fail attempt at Perlin noise algorithm

IcarusLives wrote:I'm unsure about how this works on other OS's, but I'm running Win10. From what testing I have done. You must notice that there are an equ number of digits. I "believe" this works, because 'IF' will ignore the period if comparing gtr, geq, lss, or leq. Much like comparing the number as a whole number.
1) I gave you an example (with the same numbers of digits) where it fails (although i have added doublequotes;
you could enhance it (removing the doublequotes in order to be nearer to your first ":clamp if" instruction) to:

Code: Select all

``Z:\>if -1.23400 lss 0.00000 (echo ok) else echo failfailZ:\>``
Your ":clamp" function depends on this case when clamping (should clamp -1.23400 to 0.00000, but it doesn't).

2) The "batch if" command doesn't ignore dots or something like that.
Instead if the comparands are not (decimal/octal/hexadecimal) integer numbers, then they are compared as (UCS-2) strings:
But i admit that in this case the result is unexpected... (because in UCS-2 '-' == 0x002D < 0x0030 == '0'; so the above if instruction should return ok),
so Microsoft seems to use a custom sort order (at least under "my" Win10 32-bit.).

Examples:

Code: Select all

``Z:\>if .0 lss 0. echo failfailZ:\>rem because of ('.' == 0x002E < 0x0030 == '0')Z:\>if -1.23400 lss 0.00000 (echo ok) else echo failfailZ:\>if -123400 lss 000000 (echo ok) else echo failokZ:\>``

3) Actually your implementation doesn't ensure that the floating point numbers have the same number of digits; example:
6.54321 versus 76.54321.

4) Even if you were using the same number of digits the result might be unexpected

Code: Select all

``Z:\>if -1.2 lss +1.2 (echo ok) else echo failfailZ:\>``

5) Your above "if" test cases the dot is compared to itself (if reached by comparison).

penpen

IcarusLives
Posts: 34
Joined: 17 Jan 2016 23:55

### Re: Fail attempt at Perlin noise algorithm

penpen wrote:snip

Ahh, ofc. Perhaps a better way would be to split them using . as a delimeter and do comparisons without it. This should result more accurately.

Aacini
Expert
Posts: 1469
Joined: 06 Dec 2011 22:15
Location: México City, México

### Re: Fail attempt at Perlin noise algorithm

I like this type of applications, so I read the Wikipedia article and then tried to review your program, but this was very hard to me because the code organization and the frequent jumps required to review parameters and values defined elsewhere... So I wrote my own version instead:

Code: Select all

``@echo offsetlocal EnableDelayedExpansionrem Define the limits, step and edges for the testset /A start=-4, step=9, end=108,  edge0=1, edge1=99rem Define the number of decimalsset /A decimals=3rem Define the values used to manage fixed point arithmeticrem http://www.dostips.com/forum/viewtopic.php?f=3&t=2704&p=12523#p12523set /A one=1, decimalsP1=decimals+1for /L %%i in (1,1,%decimals%) do set "one=!one!0"rem Define clamp(x) and smoothstep(x) functionsrem http://www.dostips.com/forum/viewtopic.php?f=3&t=6744set "clamp(x)=(x - edge0)*one/(edge1 - edge0)"set "smoothstep(x)=(3*one - 2*x) * x/one * x/one"rem Insert a TAB after the equal sign:set "TAB=   "clsecho edge0=%edge0%,  edge1=%edge1%echo/echo x!TAB!clamp!TAB!smoothstepecho --------------------------set /A edge0*=one, edge1*=onefor /L %%a in (%start%,%step%,%end%) do (   set /A "r=%%a*one, x=%clamp(x):x=r%"   if !x! lss 0 (set "x=0") else if !x! gtr %one% set "x=%one%"   set /A "smooth=%smoothstep(x)%"   set "clamp=000000000!x!" & set "clamp=!clamp:~-%decimalsP1%!   set "smooth=000000000!smooth!" & set "smooth=!smooth:~-%decimalsP1%!   echo %%a!TAB!!clamp:~0,-%decimals%!.!clamp:~-%decimals%!!TAB!!smooth:~0,-%decimals%!.!smooth:~-%decimals%!)``

Output:

Code: Select all

``edge0=1,  edge1=99x       clamp   smoothstep---------------------------4      0.000   0.0005       0.040   0.00414      0.132   0.04723      0.224   0.12732      0.316   0.23641      0.408   0.36350      0.500   0.50059      0.591   0.63468      0.683   0.76277      0.775   0.87086      0.867   0.95195      0.959   0.994104     1.000   1.000``

Antonio

IcarusLives
Posts: 34
Joined: 17 Jan 2016 23:55

### Re: Fail attempt at Perlin noise algorithm

Aacini wrote:I like this type of applications, so I read the Wikipedia article and then tried to review your program, but this was very hard to me because the code organization and the frequent jumps required to review parameters and values defined elsewhere... So I wrote my own version instead:
Antonio

Oh wow that's neat! Now all that's left is using the values from smoothstep and place them into Perlin noise ^-^

penpen
Expert
Posts: 1483
Joined: 23 Jun 2013 06:15
Location: Germany

### Re: Fail attempt at Perlin noise algorithm

I'm unsure whether you wanted to implement Perlin noise on your own, or not.
If you don't know how to proceed, then just implement all other dependencies before implementing the function perlin:
All line by line.

If you "fear" the p (or permutation) array (which most disencourage), then note that it might be easier than most people fear; for example you could do something like this:

Code: Select all

``@echo offsetlocal enableExtensions enableDelayedExpansionset /A "i=0, j=256"for %%a in (                                                          151,160,137,91,90,15,   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180) do set /A "p[!i!]=%%a, p[!j!]=%%a, i+=1, j+=1"set "i="set "j=":: ...set p[endlocalgoto :eof``

penpen

IcarusLives
Posts: 34
Joined: 17 Jan 2016 23:55

### Re: Fail attempt at Perlin noise algorithm

penpen wrote:I'm unsure whether you wanted to implement Perlin noise on your own, or not.
If you don't know how to proceed, then just implement all other dependencies before implementing the function perlin:
All line by line.

If you "fear" the p (or permutation) array (which most disencourage), then note that it might be easier than most people fear; for example you could do something like this:

Code: Select all

``@echo offsetlocal enableExtensions enableDelayedExpansionset /A "i=0, j=256"for %%a in (                                                          151,160,137,91,90,15,   131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,   190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,   88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,   77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,   102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,   135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,   5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,   223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,   129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,   251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,   49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,   138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180) do set /A "p[!i!]=%%a, p[!j!]=%%a, i+=1, j+=1"set "i="set "j=":: ...set p[endlocalgoto :eof``

penpen

My apologies for the absence, I've been up to my usual tinkering. Thank you for your advice, penpen ^-^