# DosTips.com

A Forum all about DOS Batch
 It is currently 21 Nov 2017 07:36

 All times are UTC-06:00

 Post new topic  Reply to topic Page 1 of 1 [ 9 posts ]
 Print view Previous topic | Next topic
Author Message
 Post subject: Fail attempt at Perlin noise algorithmPostPosted: 01 Jan 2017 23:46
 Offline

Joined: 17 Jan 2016 23:55
Posts: 34
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.

Top
 Post subject: Re: Fail attempt at Perlin noise algorithmPostPosted: 02 Jan 2017 07:34
 Offline Expert

Joined: 23 Jun 2013 06:15
Posts: 1441
Location: Germany
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

Top
 Post subject: Re: Fail attempt at Perlin noise algorithmPostPosted: 02 Jan 2017 14:59
 Offline

Joined: 17 Jan 2016 23:55
Posts: 34
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>`

Top
 Post subject: Re: Fail attempt at Perlin noise algorithmPostPosted: 03 Jan 2017 10:37
 Offline Expert

Joined: 23 Jun 2013 06:15
Posts: 1441
Location: Germany
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

Top
 Post subject: Re: Fail attempt at Perlin noise algorithmPostPosted: 03 Jan 2017 10:57
 Offline

Joined: 17 Jan 2016 23:55
Posts: 34
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.

Top
 Post subject: Re: Fail attempt at Perlin noise algorithmPostPosted: 03 Jan 2017 19:24
 Offline Expert

Joined: 06 Dec 2011 22:15
Posts: 1460
Location: México City, México
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

Top
 Post subject: Re: Fail attempt at Perlin noise algorithmPostPosted: 03 Jan 2017 19:41
 Offline

Joined: 17 Jan 2016 23:55
Posts: 34
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 ^-^

Top
 Post subject: Re: Fail attempt at Perlin noise algorithmPostPosted: 08 Jan 2017 13:20
 Offline Expert

Joined: 23 Jun 2013 06:15
Posts: 1441
Location: Germany
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

Top
 Post subject: Re: Fail attempt at Perlin noise algorithmPostPosted: 08 Jan 2017 17:50
 Offline

Joined: 17 Jan 2016 23:55
Posts: 34
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 ^-^

Top
 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Post new topic  Reply to topic Page 1 of 1 [ 9 posts ]

 All times are UTC-06:00

#### Who is online

Users browsing this forum: No registered users and 13 guests

 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum

Search for:
 Jump to:  Select a forum ------------------ DosTips - Dos Batch    DOS Batch Forum