# MINIMAL PYTHON ONLY DYNOISE MODULE IMPLEMENTATION from math import floor, pow class NGEN: def __init__(self, seed=1): self.InitNoise(seed) def InitNoise(self, seed): self.IA = 16807 self.IM = 2147483647 self.AM = 1.0/self.IM self.IQ = 127773 self.IR = 2836 self.MASK = 123459876 self.seed = seed self.__InitFNoise() def __InitFNoise(self, MaxNoise=16): 'Intialize noise module with size MaxNoise (must be a power of 2)' self.NK1 = MaxNoise+1 self.NK2 = self.NK1*self.NK1 self.NCUBE = self.NK2*self.NK1 self.NMask = MaxNoise-1 self.xyz1 = 1 self.xy1z = self.NK1 self.xy1z1 = self.NK1+1 self.x1yz = self.NK2 self.x1yz1 = self.NK2+1 self.x1y1z = self.NK2+self.NK1 self.x1y1z1 = self.NK2+self.NK1+1 self.NMTX = [] for i in range(self.NCUBE): self.NMTX.append(2.0*self.random()-1.0) for x in range(self.NK1): i = x if i==MaxNoise: i=0 for y in range(self.NK1): j = y if j==MaxNoise: j=0 for z in range(self.NK1): k = z if k==MaxNoise: k=0 self.NMTX[x*self.NK2 + y*self.NK1 + z] = self.NMTX[i*self.NK2 + j*self.NK1 + k] def FNoise(self, pos): 'Return a noise value at position x,y,z' x = abs(pos[0]) y = abs(pos[1]) z = abs(pos[2]) try: ix = int(x) & self.NMask iy = int(y) & self.NMask iz = int(z) & self.NMask except: #float too large ix = int(x % self.MaxNoise) iy = int(y % self.MaxNoise) iz = int(z % self.MaxNoise) ox = x - floor(x) oy = y - floor(y) oz = z - floor(z) ox = ox * ox * (3.0 - 2.0 * ox) IDX = ix*self.NK2 + iy*self.NK1 + iz NS = self.NMTX p000 = NS[IDX] p001 = NS[IDX + self.xyz1] p010 = NS[IDX + self.xy1z] p011 = NS[IDX + self.xy1z1] p00 = (NS[IDX + self.x1yz] - p000) * ox + p000 p01 = (NS[IDX + self.x1yz1] - p001) * ox + p001 p10 = (NS[IDX + self.x1y1z] - p010) * ox + p010 p11 = (NS[IDX + self.x1y1z1] - p011) * ox + p011 oy = oy * oy * (3.0 - 2.0 * oy) p0 = (p10 - p00) * oy + p00 p1 = (p11 - p01) * oy + p01 return ((p1 - p0) * (oz * oz * (3.0 - 2.0 * oz)) + p0) def HTerrain(self, pos, H, lacunarity, octaves, offset): pwHL = pwr = pow(lacunarity, -H) v = [pos[0], pos[1], pos[2]] # don't modify original val = offset + self.FNoise(v) v[0] *= lacunarity v[1] *= lacunarity v[2] *= lacunarity # fractal build for i in range(1,octaves): inc = (self.FNoise(v) + offset) * pwr * val val += inc pwr *= pwHL if pwr<1.0e-5: break v[0] *= lacunarity v[1] *= lacunarity v[2] *= lacunarity # remainder rem = octaves - floor(octaves) if rem!=0.0: inc = (self.FNoise(v) + offset) * pwr val += rem * inc * val return val def random(self): # minimal standard # no lin.con. (int.overfl.) self.seed ^= self.MASK k = self.seed / self.IQ self.seed = self.IA * (self.seed - k*self.IQ) - self.IR*k if self.seed<0: self.seed += self.IM R = self.AM * self.seed self.seed ^= self.MASK return R # as module NG = NGEN() def InitNoise(seed): NG.InitNoise(seed) def random(): return NG.random() def HTerrain(pos, H, lacunarity, octaves, offset): return NG.HTerrain(pos, H, lacunarity, octaves, offset)