Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
3D Perlin noise ?
#1
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
hink Global, Make Symp' All ! ®
[Image: Banner.gif]
Reply
#2
Seems noone has it Wink
Reply
#3
[Image: TcRay8.jpg]

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:

RND(-RND(f(x,y,z))) instead of RND(-f(x,y,z).

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).


Downloadable from the same website:
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:
hink Global, Make Symp' All ! ®
[Image: Banner.gif]
Reply
#4
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
hink Global, Make Symp' All ! ®
[Image: Banner.gif]
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)