Qbasicnews.com
December 03, 2021, 12:57:15 PM
 Pages: [1]
 Author Topic: 3D Perlin noise ?  (Read 3759 times)
Jark
Ancient Guru

Posts: 566

 « on: September 11, 2003, 04:16:52 AM »

Antoni Gual has sent me a superb prog by Entropy that has a 3D perlin algorithm, but it's quite complex.

I have now a fine (and fast) 2D routine, that creates tileable 129x129 Perlin noise (cf below), but I must use a different technique for a 3D routine (because DIM Noise(129,129,129) creates an overflow with QB, of course). I have some ideas about using RND with an argument, like Entropy did, but it will take time to write this.

Has anybody a good 3D perlin noise routine , in QB ?

Code:

' In Main Prog:
DIM Noise%(129,129)

SUB Init.Perlin

Persistence! = 1.5
Octaves% = 6: Span% = 2 ^ Octaves% + 1
RANDOMIZE TIMER

' Init the corners
Noise%(1, 1) = 128
Noise%(1, Span%) = 128
Noise%(Span%, 1) = 128
Noise%(Span%, Span%) = 128

' Init the edges
FOR Rank% = 1 TO Octaves%

Grid% = 2 ^ (Octaves% - Rank% + 1)
nStep% = 2 ^ (Rank% - 1) + 1

FOR kx% = 1 TO nStep% - 1
x% = (kx% - 1) * Grid% + 1: y% = 1
Alt% = (Noise%(x%, y%) + Noise%(x% + Grid%, y%)) / 2
zNew% = INT(Alt% * (1 + (RND - .5) / (Persistence! ^ Rank%)))
Noise%(x% + Grid% / 2, 1) = zNew%
Noise%(x% + Grid% / 2, Span%) = zNew%
NEXT kx%

FOR ky% = 1 TO nStep% - 1
x% = 1: y% = (ky% - 1) * Grid% + 1
Alt% = (Noise%(x%, y%) + Noise%(x%, y% + Grid%)) / 2
zNew% = INT(Alt% * (1 + (RND - .5) / (Persistence! ^ Rank%)))
Noise%(1, y% + Grid% / 2) = zNew%
Noise%(Span%, y% + Grid% / 2) = zNew%
NEXT ky%

NEXT Rank%

' Fill the clouds
FOR Rank% = 1 TO Octaves%

Grid% = 2 ^ (Octaves% - Rank% + 1)
nStep% = 2 ^ (Rank% - 1) + 1

FOR kx% = 1 TO nStep% - 1
x% = (kx% - 1) * Grid% + 1
FOR ky% = 1 TO nStep% - 1
y% = (ky% - 1) * Grid% + 1

Alt% = (Noise%(x%, y%) + Noise%(x% + Grid%, y%) + Noise%(x%, y% + Grid%) + Noise%(x% + Grid%, y% + Grid%)) / 4
Noise%(x% + Grid% / 2, y% + Grid% / 2) = INT(Alt% * (1 + (RND - .5) / (Persistence! ^ Rank%)))
Alt% = (Noise%(x%, y%) + Noise%(x% + Grid%, y%)) / 2
IF y% <> 1 THEN Noise%(x% + Grid% / 2, y%) = INT(Alt% * (1 + (RND - .5) / (Persistence! ^ Rank%)))
Alt% = (Noise%(x%, y%) + Noise%(x%, y% + Grid%)) / 2
IF x% <> 1 THEN Noise%(x%, y% + Grid% / 2) = INT(Alt% * (1 + (RND - .5) / (Persistence! ^ Rank%)))
Alt% = (Noise%(x% + Grid%, y%) + Noise%(x% + Grid%, y% + Grid%)) / 2
IF (x% + Grid%) <> Span% THEN Noise%(x% + Grid%, y% + Grid% / 2) = INT(Alt% * (1 + (RND - .5) / (Persistence! ^ Rank%)))
Alt% = (Noise%(x%, y% + Grid%) + Noise%(x% + Grid%, y% + Grid%)) / 2
IF (y% + Grid%) <> Span% THEN Noise%(x% + Grid% / 2, y% + Grid%) = INT(Alt% * (1 + (RND - .5) / (Persistence! ^ Rank%)))

NEXT ky%
NEXT kx%

NEXT Rank%

END SUB
 Logged

hink Global, Make Symp' All ! ®
TheBigBasicQ
*/-\*

Posts: 4550

 « Reply #1 on: September 15, 2003, 10:06:30 AM »

Seems noone has it
 Logged
Jark
Ancient Guru

Posts: 566

 « Reply #2 on: September 15, 2003, 11:24:38 AM »

I spent a part of the week-end on it, and I just managed to make the 3D version work...

The rational was the following: to make a fast 2D perlin noise, you create a 129x129 array (or 65x65, or 33x33, depending on how many octaves you want), and you fill it via the squares division technique. The first points are the four corners, then the center (i.e. 65-65), then the 4 edges middles (1-65,65-1,129-65 and 65-129). After 7 iterations, the array is filled.

This technique can't work in 3D with QB, because you cannot declare a 129x129x129 array... So you need to calculate the proper Perlin value for a given 3D point, let's say (43,67,114). You start from the 8 corners of the cube, and you reduce the size of the cube by two at each step, until you get a 1 pixel wide cube around (43,67,114). It's easy to understand with 1 dimension only:

1-129 > (1+129)/2 = 65
1-65 >(1+65)/2 = 33
33-65 > (33+65)/2 = 49
33-49 > (33+49)/2 = 41
41-49 > (41+49)/2=45
41-45 > (41+45)/2 = 43

So you need to calculate the Perlin noise only for 1, 129,65,33,49,41 and 43...

What you need now is to control that the RND calls return always the same result for a given point (x%,y%,z%). You do this by calling RND with a NEGATIVE argument (e.g. RND(-x%)). The last step is to avoid geometric renderings (stripes, etc...) due to the fact that RND is a pseudo random number generator. I solved the issue by using:

To finalise that, you just need to add your favorite interpolation routine, and you get a complete Perlin3D!(x!,y!,z!) function.

Nota: it's quite easy to make the cube tileable, by pre-calculating 3 sides of the cube and by duplicating each of them to the opposite side (I did that in 2D in TC-Ray).

Clampdown, Clash Live in Auckland, May the 2nd, 1982 (was a Sunday, remember I got wreck drunk on this Friday, May the 7th, after the movie "Midnight Express" and a couple of beers).

Just get back to the site's main page, and get inside the only pop-up of the Mandelbrot Dazibao!

Still play my Telecaster, plugged into my old Boogie... :rotfl:
 Logged

hink Global, Make Symp' All ! ®
Jark
Ancient Guru

Posts: 566

 « Reply #3 on: September 15, 2003, 11:27:24 AM »

Well, I caught a damn cold last friday, but I still can prog :bounce:

Code:

DIM SHARED Seed&, Octaves%, Persistence!, Span%, Amplitude!(16), Power2%(16)

SUB Init.Perlin

RANDOMIZE TIMER: Seed& = 103476 * RND
Octaves% = 7: Persistence! = 1.5: Span% = 2 ^ Octaves% + 1

FOR k% = 0 TO Octaves% + 1
Power2%(k%)=2^k% : Amplitude!(k%) = (1 / Persistence!) ^ k%
NEXT k%

END SUB

FUNCTION Noise3! (a%, b%, c%)
Noise3! = RND(-RND(-a% * b%) * RND(-c%) * Seed&) - .5
END FUNCTION

FUNCTION Perlin3D (xp!, yp!, zp!)

x! = (xp! + 1) / 2 * Power2%(Octaves%) + 1
y! = (yp! + 1) / 2 * Power2%(Octaves%) + 1
z! = (zp! + 1) / 2 * Power2%(Octaves%) + 1

Rank% = 0
ax% = 1: bx% = Span%
ay% = 1: by% = Span%
az% = 1: bz% = Span%
z1% = 128: z2% = 128: z3% = 128: z4% = 128
z5% = 128: z6% = 128: z7% = 128: z8% = 128

DO UNTIL ((bx% - x!) <= 1 AND (x! - ax%) <= 1) AND ((by% - y!) <= 1 AND (y! - ay%) <= 1) AND ((bz% - z!) <= 1 AND (z! - az%) <= 1)
Rank% = Rank% + 1
Grid% = Power2%(Octaves% - Rank%)

IF bx% - x! > x! - ax% THEN
bx% = bx% - Grid%
IF by% - y! > y! - ay% THEN
by% = by% - Grid%
IF bz% - z! > z! - az% THEN
bz% = bz% - Grid%
z1n% = z1%
z2n% = (z1% + z2%) / 2
z3n% = (z1% + z2% + z3% + z4%) / 4
z4n% = (z1% + z4%) / 2
z5n% = (z1% + z5%) / 2
z6n% = (z1% + z2% + z5% + z6%) / 4
z7n% = (z1% + z2% + z3% + z4% + z5% + z6% + z7% + z8%) / 8
z8n% = (z1% + z4% + z5% + z8%) / 4
z1% = z1n%
z2% = z2n% * (1 + Noise3!(bx%, ay%, az%) * Amplitude!(Rank%))
z3% = z3n% * (1 + Noise3!(bx%, by%, az%) * Amplitude!(Rank%))
z4% = z4n% * (1 + Noise3!(ax%, by%, az%) * Amplitude!(Rank%))
z5% = z5n% * (1 + Noise3!(ax%, ay%, bz%) * Amplitude!(Rank%))
z6% = z6n% * (1 + Noise3!(bx%, ay%, bz%) * Amplitude!(Rank%))
z7% = z7n% * (1 + Noise3!(bx%, by%, bz%) * Amplitude!(Rank%))
z8% = z8n% * (1 + Noise3!(ax%, by%, bz%) * Amplitude!(Rank%))

ELSE
az% = az% + Grid%
z1n% = (z1% + z5%) / 2
z2n% = (z1% + z2% + z5% + z6%) / 4
z3n% = (z1% + z2% + z3% + z4% + z5% + z6% + z7% + z8%) / 8
z4n% = (z1% + z4% + z5% + z8%) / 4
z5n% = z5%
z6n% = (z5% + z6%) / 2
z7n% = (z5% + z6% + z7% + z8%) / 4
z8n% = (z5% + z8%) / 2
z1% = z1n% * (1 + Noise3!(ax%, ay%, az%) * Amplitude!(Rank%))
z2% = z2n% * (1 + Noise3!(bx%, ay%, az%) * Amplitude!(Rank%))
z3% = z3n% * (1 + Noise3!(bx%, by%, az%) * Amplitude!(Rank%))
z4% = z4n% * (1 + Noise3!(ax%, by%, az%) * Amplitude!(Rank%))
z5% = z5n%
z6% = z6n% * (1 + Noise3!(bx%, ay%, bz%) * Amplitude!(Rank%))
z7% = z7n% * (1 + Noise3!(bx%, by%, bz%) * Amplitude!(Rank%))
z8% = z8n% * (1 + Noise3!(ax%, by%, bz%) * Amplitude!(Rank%))

END IF
ELSE
ay% = ay% + Grid%
IF bz% - z! > z! - az% THEN
bz% = bz% - Grid%
z1n% = (z1% + z4%) / 2
z2n% = (z1% + z2% + z3% + z4%) / 4
z3n% = (z3% + z4%) / 2
z4n% = z4%
z5n% = (z1% + z4% + z5% + z8%) / 4
z6n% = (z1% + z2% + z3% + z4% + z5% + z6% + z7% + z8%) / 8
z7n% = (z4% + z3% + z7% + z8%) / 4
z8n% = (z4% + z8%) / 2
z1% = z1n% * (1 + Noise3!(ax%, ay%, az%) * Amplitude!(Rank%))
z2% = z2n% * (1 + Noise3!(bx%, ay%, az%) * Amplitude!(Rank%))
z3% = z3n% * (1 + Noise3!(bx%, by%, az%) * Amplitude!(Rank%))
z4% = z4n%
z5% = z5n% * (1 + Noise3!(ax%, ay%, bz%) * Amplitude!(Rank%))
z6% = z6n% * (1 + Noise3!(bx%, ay%, bz%) * Amplitude!(Rank%))
z7% = z7n% * (1 + Noise3!(bx%, by%, bz%) * Amplitude!(Rank%))
z8% = z8n% * (1 + Noise3!(ax%, by%, bz%) * Amplitude!(Rank%))
ELSE
az% = az% + Grid%
z1n% = (z1% + z4% + z5% + z8%) / 4
z2n% = (z1% + z2% + z3% + z4% + z5% + z6% + z7% + z8%) / 8
z3n% = (z4% + z3% + z7% + z8%) / 4
z4n% = (z4% + z8%) / 2
z5n% = (z5% + z8%) / 2
z6n% = (z5% + z6% + z7% + z8%) / 4
z7n% = (z7% + z8%) / 2
z8n% = z8%
z1% = z1n% * (1 + Noise3!(ax%, ay%, az%) * Amplitude!(Rank%))
z2% = z2n% * (1 + Noise3!(bx%, ay%, az%) * Amplitude!(Rank%))
z3% = z3n% * (1 + Noise3!(bx%, by%, az%) * Amplitude!(Rank%))
z4% = z4n% * (1 + Noise3!(ax%, by%, az%) * Amplitude!(Rank%))
z5% = z5n% * (1 + Noise3!(ax%, ay%, bz%) * Amplitude!(Rank%))
z6% = z6n% * (1 + Noise3!(bx%, ay%, bz%) * Amplitude!(Rank%))
z7% = z7n% * (1 + Noise3!(bx%, by%, bz%) * Amplitude!(Rank%))
z8% = z8n%
END IF
END IF

ELSE
ax% = ax% + Grid%
IF by% - y! > y! - ay% THEN
by% = by% - Grid%
IF bz% - z! > z! - az% THEN
bz% = bz% - Grid%
z1n% = (z1% + z2%) / 2
z2n% = z2%
z3n% = (z3% + z2%) / 2
z4n% = (z1% + z2% + z3% + z4%) / 4
z5n% = (z1% + z2% + z5% + z6%) / 4
z6n% = (z6% + z2%) / 2
z7n% = (z2% + z3% + z6% + z7%) / 4
z8n% = (z1% + z2% + z3% + z4% + z5% + z6% + z7% + z8%) / 8
z1% = z1n% * (1 + Noise3!(ax%, ay%, az%) * Amplitude!(Rank%))
z2% = z2n%
z3% = z3n% * (1 + Noise3!(bx%, by%, az%) * Amplitude!(Rank%))
z4% = z4n% * (1 + Noise3!(ax%, by%, az%) * Amplitude!(Rank%))
z5% = z5n% * (1 + Noise3!(ax%, ay%, bz%) * Amplitude!(Rank%))
z6% = z6n% * (1 + Noise3!(bx%, ay%, bz%) * Amplitude!(Rank%))
z7% = z7n% * (1 + Noise3!(bx%, by%, bz%) * Amplitude!(Rank%))
z8% = z8n% * (1 + Noise3!(ax%, by%, bz%) * Amplitude!(Rank%))
ELSE
az% = az% + Grid%
z1n% = (z1% + z2% + z5% + z6%) / 4
z2n% = (z2% + z6%) / 2
z3n% = (z2% + z3% + z6% + z7%) / 4
z4n% = (z1% + z2% + z3% + z4% + z5% + z6% + z7% + z8%) / 8
z5n% = (z5% + z6%) / 2
z6n% = z6%
z7n% = (z6% + z7%) / 2
z8n% = (z5% + z6% + z7% + z8%) / 4
z1% = z1n% * (1 + Noise3!(ax%, ay%, az%) * Amplitude!(Rank%))
z2% = z2n% * (1 + Noise3!(bx%, ay%, az%) * Amplitude!(Rank%))
z3% = z3n% * (1 + Noise3!(bx%, by%, az%) * Amplitude!(Rank%))
z4% = z4n% * (1 + Noise3!(ax%, by%, az%) * Amplitude!(Rank%))
z5% = z5n% * (1 + Noise3!(ax%, ay%, bz%) * Amplitude!(Rank%))
z6% = z6n%
z7% = z7n% * (1 + Noise3!(bx%, by%, bz%) * Amplitude!(Rank%))
z8% = z8n% * (1 + Noise3!(ax%, by%, bz%) * Amplitude!(Rank%))
END IF
ELSE
ay% = ay% + Grid%
IF bz% - z! > z! - az% THEN
bz% = bz% - Grid%
z1n% = (z1% + z2% + z3% + z4%) / 4
z2n% = (z3% + z2%) / 2
z3n% = z3%
z4n% = (z4% + z3%) / 2
z5n% = (z1% + z2% + z3% + z4% + z5% + z6% + z7% + z8%) / 8
z6n% = (z2% + z3% + z6% + z7%) / 4
z7n% = (z3% + z7%) / 2
z8n% = (z3% + z4% + z7% + z8%) / 4
z1% = z1n% * (1 + Noise3!(ax%, ay%, az%) * Amplitude!(Rank%))
z2% = z2n% * (1 + Noise3!(bx%, ay%, az%) * Amplitude!(Rank%))
z3% = z3n%
z4% = z4n% * (1 + Noise3!(ax%, by%, az%) * Amplitude!(Rank%))
z5% = z5n% * (1 + Noise3!(ax%, ay%, bz%) * Amplitude!(Rank%))
z6% = z6n% * (1 + Noise3!(bx%, ay%, bz%) * Amplitude!(Rank%))
z7% = z7n% * (1 + Noise3!(bx%, by%, bz%) * Amplitude!(Rank%))
z8% = z8n% * (1 + Noise3!(ax%, by%, bz%) * Amplitude!(Rank%))
ELSE
az% = az% + Grid%
z1n% = (z1% + z2% + z3% + z4% + z5% + z6% + z7% + z8%) / 8
z2n% = (z2% + z3% + z6% + z7%) / 4
z3n% = (z3% + z7%) / 2
z4n% = (z3% + z4% + z7% + z8%) / 4
z5n% = (z5% + z6% + z7% + z8%) / 4
z6n% = (z6% + z7%) / 2
z7n% = z7%
z8n% = (z7% + z8%) / 2
z1% = z1n% * (1 + Noise3!(ax%, ay%, az%) * Amplitude!(Rank%))
z2% = z2n% * (1 + Noise3!(bx%, ay%, az%) * Amplitude!(Rank%))
z3% = z3n% * (1 + Noise3!(bx%, by%, az%) * Amplitude!(Rank%))
z4% = z4n% * (1 + Noise3!(ax%, by%, az%) * Amplitude!(Rank%))
z5% = z5n% * (1 + Noise3!(ax%, ay%, bz%) * Amplitude!(Rank%))
z6% = z6n% * (1 + Noise3!(bx%, ay%, bz%) * Amplitude!(Rank%))
z7% = z7n%
z8% = z8n% * (1 + Noise3!(ax%, by%, bz%) * Amplitude!(Rank%))
END IF
END IF

END IF
LOOP

zp1! = z1% * (bx% - x!) + z2% * (x! - ax%)
zp2! = z4% * (bx% - x!) + z3% * (x! - ax%)
zp12! = zp1! * (by% - y!) + zp2! * (y! - ay%)

zp3! = z5% * (bx% - x!) + z6% * (x! - ax%)
zp4! = z8% * (bx% - x!) + z7% * (x! - ax%)
zp34! = zp3! * (by% - y!) + zp4! * (y! - ay%)

zp! = zp12! * (bz% - z!) + zp34! * (z! - az%)

Perlin3D! = zp! / 255

END FUNCTION

 Logged

hink Global, Make Symp' All ! ®
 Pages: [1]