expre-gen/blender/3.4/scripts/addons/ant_landscape/ant_noise.py
2025-10-17 09:47:23 +08:00

708 lines
22 KiB
Python

# SPDX-License-Identifier: GPL-2.0-or-later
# Another Noise Tool - Noise and Effects
# Jimmy Hazevoet
import bpy
from mathutils.noise import (
seed_set,
noise,
turbulence,
turbulence_vector,
fractal,
hybrid_multi_fractal,
multi_fractal,
ridged_multi_fractal,
hetero_terrain,
random_unit_vector,
variable_lacunarity,
voronoi,
)
from math import (
floor, sqrt,
sin, cos, pi,
)
noise_basis_default = "BLENDER"
noise_basis = [
("BLENDER", "Blender", "Blender default noise", 0),
("PERLIN_ORIGINAL", "Perlin", "Perlin noise", 1),
("PERLIN_NEW", "New Perlin", "New Perlin noise", 2),
("VORONOI_F1", "Voronoi F1", "Voronoi F1", 3),
("VORONOI_F2", "Voronoi F2", "Voronoi F2", 4),
("VORONOI_F3", "Voronoi F3", "Voronoi F3", 5),
("VORONOI_F4", "Voronoi F4", "Voronoi F4", 6),
("VORONOI_F2F1", "Voronoi F2-F1", "Voronoi F2-F1", 7),
("VORONOI_CRACKLE", "Voronoi Crackle", "Voronoi Crackle", 8),
("CELLNOISE", "Cell Noise", "Cell noise", 9)
]
# ------------------------------------------------------------
# Height scale:
def Height_Scale(input, iscale, offset, invert):
if invert != 0:
return (1.0 - input) * iscale + offset
else:
return input * iscale + offset
# Functions for marble_noise and effects:
def Dist(x, y):
return sqrt((x * x) + (y * y))
def sin_bias(a):
return 0.5 + 0.5 * sin(a)
def cos_bias(a):
return 0.5 + 0.5 * cos(a)
def tri_bias(a):
b = 2 * pi
a = 1 - 2 * abs(floor((a * (1 / b)) + 0.5) - (a * (1 / b)))
return a
def saw_bias(a):
b = 2 * pi
n = int(a / b)
a -= n * b
if a < 0:
a += b
return a / b
def soft(a):
return a
def sharp(a):
return a**0.5
def sharper(a):
return sharp(sharp(a))
def no_bias(a):
return a
def shapes(x, y, z, shape=0):
p = pi
if shape == 1:
# ring
x = x * p
y = y * p
s = cos(x**2 + y**2) / (x**2 + y**2 + 0.5)
elif shape == 2:
# swirl
x = x * p
y = y * p
s = ((x * sin(x * x + y * y) + y * cos(x * x + y * y)) / (x**2 + y**2 + 0.5))
elif shape == 3:
# bumps
x = x * p
y = y * p
z = z * p
s = 1 - ((cos(x * p) + cos(y * p) + cos(z * p)) - 0.5)
elif shape == 4:
# wave
x = x * p * 2
y = y * p * 2
s = sin(x + sin(y))
elif shape == 5:
# z grad.
s = (z * p)
elif shape == 6:
# y grad.
s = (y * p)
elif shape == 7:
# x grad.
s = (x * p)
else:
# marble default
s = ((x + y + z) * 5)
return s
# marble_noise
def marble_noise(x, y, z, origin, size, shape, bias, sharpnes, turb, depth, hard, basis, amp, freq):
s = shapes(x, y, z, shape)
x += origin[0]
y += origin[1]
z += origin[2]
value = s + turb * turbulence_vector((x, y, z), depth, hard, noise_basis=basis)[1]
if bias == 1:
value = cos_bias(value)
elif bias == 2:
value = tri_bias(value)
elif bias == 3:
value = saw_bias(value)
else:
value = sin_bias(value)
if sharpnes == 1:
value = 1.0 - sharp(value)
elif sharpnes == 2:
value = 1.0 - sharper(value)
elif sharpnes == 3:
value = soft(value)
elif sharpnes == 4:
value = sharp(value)
elif sharpnes == 5:
value = sharper(value)
else:
value = 1.0 - soft(value)
return value
# vl_noise_turbulence:
def vlnTurbMode(coords, distort, basis, vlbasis, hardnoise):
# hard noise
if hardnoise:
return (abs(-variable_lacunarity(coords, distort, noise_type1=basis, noise_type2=vlbasis)))
# soft noise
else:
return variable_lacunarity(coords, distort, noise_type1=basis, noise_type2=vlbasis)
def vl_noise_turbulence(coords, distort, depth, basis, vlbasis, hardnoise, amp, freq):
x, y, z = coords
value = vlnTurbMode(coords, distort, basis, vlbasis, hardnoise)
i = 0
for i in range(depth):
i += 1
value += vlnTurbMode((x * (freq * i), y * (freq * i), z * (freq * i)),
distort, basis, vlbasis, hardnoise) * (amp * 0.5 / i)
return value
# duo_multiFractal:
def double_multiFractal(coords, H, lacunarity, octaves, offset, gain, basis, vlbasis):
x, y, z = coords
n1 = multi_fractal((x * 1.5 + 1, y * 1.5 + 1, z * 1.5 + 1), 1.0, 1.0, 1.0, noise_basis=basis) * (offset * 0.5)
n2 = multi_fractal((x - 1, y - 1, z - 1), H, lacunarity, octaves, noise_basis=vlbasis) * (gain * 0.5)
return (n1 * n1 + n2 * n2) * 0.5
# distorted_heteroTerrain:
def distorted_heteroTerrain(coords, H, lacunarity, octaves, offset, distort, basis, vlbasis):
x, y, z = coords
h1 = (hetero_terrain((x, y, z), 1.0, 2.0, 1.0, 1.0, noise_basis=basis) * 0.5)
d = h1 * distort
h2 = (hetero_terrain((x + d, y + d, z + d), H, lacunarity, octaves, offset, noise_basis=vlbasis) * 0.25)
return (h1 * h1 + h2 * h2) * 0.5
# SlickRock:
def slick_rock(coords, H, lacunarity, octaves, offset, gain, distort, basis, vlbasis):
x, y, z = coords
n = multi_fractal((x, y, z), 1.0, 2.0, 2.0, noise_basis=basis) * distort * 0.25
r = ridged_multi_fractal((x + n, y + n, z + n), H, lacunarity, octaves, offset + 0.1, gain * 2, noise_basis=vlbasis)
return (n + (n * r)) * 0.5
# vlhTerrain
def vl_hTerrain(coords, H, lacunarity, octaves, offset, basis, vlbasis, distort):
x, y, z = coords
ht = hetero_terrain((x, y, z), H, lacunarity, octaves, offset, noise_basis=basis) * 0.25
vl = ht * variable_lacunarity((x, y, z), distort, noise_type1=basis, noise_type2=vlbasis) * 0.5 + 0.5
return vl * ht
# another turbulence
def ant_turbulence(coords, depth, hardnoise, nbasis, amp, freq, distortion):
x, y, z = coords
t = turbulence_vector((x / 2, y / 2, z / 2), depth, 0, noise_basis=nbasis,
amplitude_scale=amp, frequency_scale=freq) * 0.5 * distortion
return turbulence((t[0], t[1], t[2]), 2, hardnoise, noise_basis="VORONOI_F1") * 0.5 + 0.5
# rocks noise
def rocks_noise(coords, depth, hardnoise, nbasis, distortion):
x, y, z = coords
p = turbulence((x, y, z), 4, 0, noise_basis='BLENDER') * 0.125 * distortion
xx, yy, zz = x, y, z
a = turbulence((xx + p, yy + p, zz), 2, 0, noise_basis='VORONOI_F2F1')
pa = a * 0.1875 * distortion
b = turbulence((x, y, z + pa), depth, hardnoise, noise_basis=nbasis)
return ((a + 0.5 * (b - a)) * 0.5 + 0.5)
# shattered_hterrain:
def shattered_hterrain(coords, H, lacunarity, octaves, offset, distort, basis):
x, y, z = coords
d = (turbulence_vector(coords, 6, 0)[0] * 0.5 + 0.5) * distort * 0.5
t1 = (turbulence_vector((x + d, y + d, z + d), 0, 0, noise_basis='VORONOI_F2F1')[0] + 0.5)
t2 = (hetero_terrain((x * 2, y * 2, z * 2), H, lacunarity, octaves, offset, noise_basis=basis) * 0.5)
return ((t1 * t2) + t2 * 0.5) * 0.5
# strata_hterrain
def strata_hterrain(coords, H, lacunarity, octaves, offset, distort, basis):
x, y, z = coords
value = hetero_terrain((x, y, z), H, lacunarity, octaves, offset, noise_basis=basis) * 0.5
steps = (sin(value * (distort * 5) * pi) * (0.1 / (distort * 5) * pi))
return (value * (1.0 - 0.5) + steps * 0.5)
# Planet Noise by: Farsthary
# https://farsthary.com/2010/11/24/new-planet-procedural-texture/
def planet_noise(coords, oct=6, hard=0, noisebasis='PERLIN_ORIGINAL', nabla=0.001):
x, y, z = coords
d = 0.001
offset = nabla * 1000
x = turbulence((x, y, z), oct, hard, noise_basis=noisebasis)
y = turbulence((x + offset, y, z), oct, hard, noise_basis=noisebasis)
z = turbulence((x, y + offset, z), oct, hard, noise_basis=noisebasis)
xdy = x - turbulence((x, y + d, z), oct, hard, noise_basis=noisebasis)
xdz = x - turbulence((x, y, z + d), oct, hard, noise_basis=noisebasis)
ydx = y - turbulence((x + d, y, z), oct, hard, noise_basis=noisebasis)
ydz = y - turbulence((x, y, z + d), oct, hard, noise_basis=noisebasis)
zdx = z - turbulence((x + d, y, z), oct, hard, noise_basis=noisebasis)
zdy = z - turbulence((x, y + d, z), oct, hard, noise_basis=noisebasis)
return (zdy - ydz), (zdx - xdz), (ydx - xdy)
# ----------------------------------------------------------------------
# v.1.04 Effect functions:
def maximum(a, b):
if (a > b):
b = a
return b
def minimum(a, b):
if (a < b):
b = a
return b
def Mix_Modes(a, b, mixfactor, mode):
mode = int(mode)
a = a * (1.0 - mixfactor)
b = b * (1.0 + mixfactor)
# 1 mix
if mode == 0:
return (a * (1.0 - 0.5) + b * 0.5)
# 2 add
elif mode == 1:
return (a + b)
# 3 sub.
elif mode == 2:
return (a - b)
# 4 mult.
elif mode == 3:
return (a * b)
# 5 abs diff.
elif mode == 4:
return (abs(a - b))
# 6 screen
elif mode == 5:
return 1.0 - ((1.0 - a) * (1.0 - b) / 1.0)
# 7 addmodulo
elif mode == 6:
return (a + b) % 1.0
# 8 min.
elif mode == 7:
return minimum(a, b)
# 9 max.
elif mode == 8:
return maximum(a, b)
else:
return 0
Bias_Types = [sin_bias, cos_bias, tri_bias, saw_bias, no_bias]
Sharp_Types = [soft, sharp, sharper]
# Transpose effect coords:
def Trans_Effect(coords, size, loc):
x, y, z = coords
x = (x * 2.0 / size + loc[0])
y = (y * 2.0 / size + loc[1])
return x, y, z
# Effect_Basis_Function:
def Effect_Basis_Function(coords, type, bias):
bias = int(bias)
type = int(type)
x, y, z = coords
iscale = 1.0
offset = 0.0
# gradient:
if type == 1:
effect = offset + iscale * (Bias_Types[bias](x + y))
# waves / bumps:
elif type == 2:
effect = offset + iscale * 0.5 * (Bias_Types[bias](x * pi) + Bias_Types[bias](y * pi))
# zigzag:
elif type == 3:
effect = offset + iscale * Bias_Types[bias](offset + iscale * sin(x * pi + sin(y * pi)))
# wavy:
elif type == 4:
effect = offset + iscale * (Bias_Types[bias](cos(x) + sin(y) + cos(x * 2 + y * 2) - sin(-x * 4 + y * 4)))
# sine bump:
elif type == 5:
effect = offset + iscale * 1 - Bias_Types[bias]((sin(x * pi) + sin(y * pi)))
# dots:
elif type == 6:
effect = offset + iscale * (Bias_Types[bias](x * pi * 2) * Bias_Types[bias](y * pi * 2)) - 0.5
# rings:
elif type == 7:
effect = offset + iscale * (Bias_Types[bias](1.0 - (x * x + y * y)))
# spiral:
elif type == 8:
effect = offset + iscale * \
Bias_Types[bias]((x * sin(x * x + y * y) + y * cos(x * x + y * y)) / (x**2 + y**2 + 0.5)) * 2
# square / piramide:
elif type == 9:
effect = offset + iscale * Bias_Types[bias](1.0 - sqrt((x * x)**10 + (y * y)**10)**0.1)
# blocks:
elif type == 10:
effect = (0.5 - max(Bias_Types[bias](x * pi), Bias_Types[bias](y * pi)))
if effect > 0.0:
effect = 1.0
effect = offset + iscale * effect
# grid:
elif type == 11:
effect = (0.025 - min(Bias_Types[bias](x * pi), Bias_Types[bias](y * pi)))
if effect > 0.0:
effect = 1.0
effect = offset + iscale * effect
# tech:
elif type == 12:
a = max(Bias_Types[bias](x * pi), Bias_Types[bias](y * pi))
b = max(Bias_Types[bias](x * pi * 2 + 2), Bias_Types[bias](y * pi * 2 + 2))
effect = min(Bias_Types[bias](a), Bias_Types[bias](b)) * 3.0 - 2.0
if effect > 0.5:
effect = 1.0
effect = offset + iscale * effect
# crackle:
elif type == 13:
t = turbulence((x, y, 0), 6, 0, noise_basis="BLENDER") * 0.25
effect = variable_lacunarity((x, y, t), 0.25, noise_type2='VORONOI_CRACKLE')
if effect > 0.5:
effect = 0.5
effect = offset + iscale * effect
# sparse cracks noise:
elif type == 14:
effect = 2.5 * abs(noise((x, y, 0), noise_basis="PERLIN_ORIGINAL")) - 0.1
if effect > 0.25:
effect = 0.25
effect = offset + iscale * (effect * 2.5)
# shattered rock noise:
elif type == 15:
effect = 0.5 + noise((x, y, 0), noise_basis="VORONOI_F2F1")
if effect > 0.75:
effect = 0.75
effect = offset + iscale * effect
# lunar noise:
elif type == 16:
effect = 0.25 + 1.5 * voronoi((x, y, 0), distance_metric='DISTANCE_SQUARED')[0][0]
if effect > 0.5:
effect = 0.5
effect = offset + iscale * effect * 2
# cosine noise:
elif type == 17:
effect = cos(5 * noise((x, y, 0), noise_basis="BLENDER"))
effect = offset + iscale * (effect * 0.5)
# spikey noise:
elif type == 18:
n = 0.5 + 0.5 * turbulence((x * 5, y * 5, 0), 8, 0, noise_basis="BLENDER")
effect = ((n * n)**5)
effect = offset + iscale * effect
# stone noise:
elif type == 19:
effect = offset + iscale * (noise((x * 2, y * 2, 0), noise_basis="BLENDER") * 1.5 - 0.75)
# Flat Turb:
elif type == 20:
t = turbulence((x, y, 0), 6, 0, noise_basis="BLENDER")
effect = t * 2.0
if effect > 0.25:
effect = 0.25
effect = offset + iscale * effect
# Flat Voronoi:
elif type == 21:
t = 1 - voronoi((x, y, 0), distance_metric='DISTANCE_SQUARED')[0][0]
effect = t * 2 - 1.5
if effect > 0.25:
effect = 0.25
effect = offset + iscale * effect
else:
effect = 0.0
if effect < 0.0:
effect = 0.0
return effect
# fractalize Effect_Basis_Function: ------------------------------
def Effect_Function(coords, type, bias, turb, depth, frequency, amplitude):
x, y, z = coords
# turbulence:
if turb > 0.0:
t = turb * (0.5 + 0.5 * turbulence(coords, 6, 0, noise_basis="BLENDER"))
x = x + t
y = y + t
z = z + t
result = Effect_Basis_Function((x, y, z), type, bias) * amplitude
# fractalize:
if depth != 0:
i = 0
for i in range(depth):
i += 1
x *= frequency
y *= frequency
result += Effect_Basis_Function((x, y, z), type, bias) * amplitude / i
return result
# ------------------------------------------------------------
# landscape_gen
def noise_gen(coords, props):
terrain_name = props[0]
cursor = props[1]
smooth = props[2]
triface = props[3]
sphere = props[4]
land_mat = props[5]
water_mat = props[6]
texture_name = props[7]
subd_x = props[8]
subd_y = props[9]
meshsize_x = props[10]
meshsize_y = props[11]
meshsize = props[12]
rseed = props[13]
x_offset = props[14]
y_offset = props[15]
z_offset = props[16]
size_x = props[17]
size_y = props[18]
size_z = props[19]
nsize = props[20]
ntype = props[21]
nbasis = props[22]
vlbasis = props[23]
distortion = props[24]
hardnoise = int(props[25])
depth = props[26]
amp = props[27]
freq = props[28]
dimension = props[29]
lacunarity = props[30]
offset = props[31]
gain = props[32]
marblebias = int(props[33])
marblesharpnes = int(props[34])
marbleshape = int(props[35])
height = props[36]
height_invert = props[37]
height_offset = props[38]
maximum = props[39]
minimum = props[40]
falloff = int(props[41])
edge_level = props[42]
falloffsize_x = props[43]
falloffsize_y = props[44]
stratatype = props[45]
strata = props[46]
addwater = props[47]
waterlevel = props[48]
vert_group = props[49]
remove_double = props[50]
fx_mixfactor = props[51]
fx_mix_mode = props[52]
fx_type = props[53]
fx_bias = props[54]
fx_turb = props[55]
fx_depth = props[56]
fx_frequency = props[57]
fx_amplitude = props[58]
fx_size = props[59]
fx_loc_x = props[60]
fx_loc_y = props[61]
fx_height = props[62]
fx_offset = props[63]
fx_invert = props[64]
x, y, z = coords
# Origin
if rseed == 0:
origin = x_offset, y_offset, z_offset
origin_x = x_offset
origin_y = y_offset
origin_z = z_offset
o_range = 1.0
else:
# Randomise origin
o_range = 100
seed_set(rseed)
origin = random_unit_vector()
ox = (origin[0] * o_range)
oy = (origin[1] * o_range)
oz = 0
origin_x = (ox - (ox * 0.5)) + x_offset
origin_y = (oy - (oy * 0.5)) + y_offset
origin_z = oz + z_offset
ncoords = (x / (nsize * size_x) + origin_x, y / (nsize * size_y) + origin_y, z / (nsize * size_z) + origin_z)
# Noise type's
if ntype in [0, 'multi_fractal']:
value = multi_fractal(ncoords, dimension, lacunarity, depth, noise_basis=nbasis) * 0.5
elif ntype in [1, 'ridged_multi_fractal']:
value = ridged_multi_fractal(ncoords, dimension, lacunarity, depth, offset, gain, noise_basis=nbasis) * 0.5
elif ntype in [2, 'hybrid_multi_fractal']:
value = hybrid_multi_fractal(ncoords, dimension, lacunarity, depth, offset, gain, noise_basis=nbasis) * 0.5
elif ntype in [3, 'hetero_terrain']:
value = hetero_terrain(ncoords, dimension, lacunarity, depth, offset, noise_basis=nbasis) * 0.25
elif ntype in [4, 'fractal']:
value = fractal(ncoords, dimension, lacunarity, depth, noise_basis=nbasis)
elif ntype in [5, 'turbulence_vector']:
value = turbulence_vector(ncoords, depth, hardnoise, noise_basis=nbasis,
amplitude_scale=amp, frequency_scale=freq)[0]
elif ntype in [6, 'variable_lacunarity']:
value = variable_lacunarity(ncoords, distortion, noise_type1=nbasis, noise_type2=vlbasis)
elif ntype in [7, 'marble_noise']:
value = marble_noise(
(ncoords[0] - origin_x + x_offset),
(ncoords[1] - origin_y + y_offset),
(ncoords[2] - origin_z + z_offset),
(origin[0] + x_offset, origin[1] + y_offset, origin[2] + z_offset), nsize,
marbleshape, marblebias, marblesharpnes,
distortion, depth, hardnoise, nbasis, amp, freq
)
elif ntype in [8, 'shattered_hterrain']:
value = shattered_hterrain(ncoords, dimension, lacunarity, depth, offset, distortion, nbasis)
elif ntype in [9, 'strata_hterrain']:
value = strata_hterrain(ncoords, dimension, lacunarity, depth, offset, distortion, nbasis)
elif ntype in [10, 'ant_turbulence']:
value = ant_turbulence(ncoords, depth, hardnoise, nbasis, amp, freq, distortion)
elif ntype in [11, 'vl_noise_turbulence']:
value = vl_noise_turbulence(ncoords, distortion, depth, nbasis, vlbasis, hardnoise, amp, freq)
elif ntype in [12, 'vl_hTerrain']:
value = vl_hTerrain(ncoords, dimension, lacunarity, depth, offset, nbasis, vlbasis, distortion)
elif ntype in [13, 'distorted_heteroTerrain']:
value = distorted_heteroTerrain(ncoords, dimension, lacunarity, depth, offset, distortion, nbasis, vlbasis)
elif ntype in [14, 'double_multiFractal']:
value = double_multiFractal(ncoords, dimension, lacunarity, depth, offset, gain, nbasis, vlbasis)
elif ntype in [15, 'rocks_noise']:
value = rocks_noise(ncoords, depth, hardnoise, nbasis, distortion)
elif ntype in [16, 'slick_rock']:
value = slick_rock(ncoords, dimension, lacunarity, depth, offset, gain, distortion, nbasis, vlbasis)
elif ntype in [17, 'planet_noise']:
value = planet_noise(ncoords, depth, hardnoise, nbasis)[2] * 0.5 + 0.5
elif ntype in [18, 'blender_texture']:
if texture_name != "" and texture_name in bpy.data.textures:
value = bpy.data.textures[texture_name].evaluate(ncoords)[3]
else:
value = 0.0
else:
value = 0.5
# Effect mix
val = value
if fx_type in [0, "0"]:
fx_mixfactor = -1.0
fxval = val
else:
fxcoords = Trans_Effect((x, y, z), fx_size, (fx_loc_x, fx_loc_y))
effect = Effect_Function(fxcoords, fx_type, fx_bias, fx_turb, fx_depth, fx_frequency, fx_amplitude)
effect = Height_Scale(effect, fx_height, fx_offset, fx_invert)
fxval = Mix_Modes(val, effect, fx_mixfactor, fx_mix_mode)
value = fxval
# Adjust height
value = Height_Scale(value, height, height_offset, height_invert)
# Edge falloff:
if not sphere:
if falloff:
ratio_x, ratio_y = abs(x) * 2 / meshsize_x, abs(y) * 2 / meshsize_y
fallofftypes = [
0,
sqrt(ratio_y**falloffsize_y),
sqrt(ratio_x**falloffsize_x),
sqrt(ratio_x**falloffsize_x + ratio_y**falloffsize_y)
]
dist = fallofftypes[falloff]
value -= edge_level
if dist < 1.0:
dist = (dist * dist * (3 - 2 * dist))
value = (value - value * dist) + edge_level
else:
value = edge_level
# Strata / terrace / layers
if stratatype not in [0, "0"]:
if stratatype in [1, "1"]:
strata = strata / height
strata *= 2
steps = (sin(value * strata * pi) * (0.1 / strata * pi))
value = (value * 0.5 + steps * 0.5) * 2.0
elif stratatype in [2, "2"]:
strata = strata / height
steps = -abs(sin(value * strata * pi) * (0.1 / strata * pi))
value = (value * 0.5 + steps * 0.5) * 2.0
elif stratatype in [3, "3"]:
strata = strata / height
steps = abs(sin(value * strata * pi) * (0.1 / strata * pi))
value = (value * 0.5 + steps * 0.5) * 2.0
elif stratatype in [4, "4"]:
strata = strata / height
value = int(value * strata) * 1.0 / strata
elif stratatype in [5, "5"]:
strata = strata / height
steps = (int(value * strata) * 1.0 / strata)
value = (value * (1.0 - 0.5) + steps * 0.5)
# Clamp height min max
if (value < minimum):
value = minimum
if (value > maximum):
value = maximum
return value