Tree Generator v1.3.0: Sub-Aeste ohne Nadelspitzen

Mindestdicke (Tip Blunt) wirkt jetzt auf Verjuengung*Kuppel statt nur auf die
Kuppel. Duennster Querschnitt 0.8 mm -> 7.5 mm (gemessen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 10:46:30 +02:00
co-authored by Claude Opus 4.8
parent bb576292fa
commit 89aa74c056
5 changed files with 28 additions and 32 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
schema_version = "1.0.0" schema_version = "1.0.0"
id = "stylized_tree_generator" id = "stylized_tree_generator"
version = "1.2.0" version = "1.3.0"
name = "Stylized Tree Generator" name = "Stylized Tree Generator"
tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen" tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen"
maintainer = "D4rkst3r" maintainer = "D4rkst3r"
+4 -4
View File
@@ -32,7 +32,7 @@
"id": "stylized_tree_generator", "id": "stylized_tree_generator",
"name": "Stylized Tree Generator", "name": "Stylized Tree Generator",
"tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen", "tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen",
"version": "1.2.0", "version": "1.3.0",
"type": "add-on", "type": "add-on",
"maintainer": "D4rkst3r", "maintainer": "D4rkst3r",
"license": [ "license": [
@@ -48,9 +48,9 @@
"Mesh", "Mesh",
"Modeling" "Modeling"
], ],
"archive_url": "./stylized_tree_generator-1.2.0.zip", "archive_url": "./stylized_tree_generator-1.3.0.zip",
"archive_size": 10862, "archive_size": 10852,
"archive_hash": "sha256:8297d75cf7b8d73189471b480f65e98861ee73840f0ab387fb9f2141fa80a083" "archive_hash": "sha256:31c7a72133a6c28d24f95d661cabf0be56dc00c3102ad57a4a3c1e1c5a30bcd4"
} }
] ]
} }
Binary file not shown.
Binary file not shown.
+23 -27
View File
@@ -1,7 +1,7 @@
bl_info = { bl_info = {
"name": "Stylized Tree Generator", "name": "Stylized Tree Generator",
"author": "D4rkst3r", "author": "D4rkst3r",
"version": (1, 2, 0), "version": (1, 3, 0),
"blender": (4, 2, 0), "blender": (4, 2, 0),
"location": "View3D > Sidebar > Tree Gen", "location": "View3D > Sidebar > Tree Gen",
"description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen", "description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen",
@@ -206,9 +206,6 @@ def build_group():
inv = N("ShaderNodeMath"); inv.location = (-420, 60); inv.operation = 'SUBTRACT' inv = N("ShaderNodeMath"); inv.location = (-420, 60); inv.operation = 'SUBTRACT'
inv.inputs[0].default_value = 1.0 inv.inputs[0].default_value = 1.0
L(tf.outputs[0], inv.inputs[1]) L(tf.outputs[0], inv.inputs[1])
trad0 = N("ShaderNodeMath"); trad0.location = (-260, 60); trad0.operation = 'MULTIPLY'
L(V["Trunk Radius"], trad0.inputs[0]); L(inv.outputs[0], trad0.inputs[1])
# Kuppel-Profil: (1 - f^3)^0.5 -> breite, gleichmaessige Kuppe. Mit einem # Kuppel-Profil: (1 - f^3)^0.5 -> breite, gleichmaessige Kuppe. Mit einem
# zu spaeten/steilen Profil (f^8) trifft die Rundung nur 1-2 Resample- # zu spaeten/steilen Profil (f^8) trifft die Rundung nur 1-2 Resample-
# Punkte und wird zum KEGEL. Breit + genug Punkte = runde Kuppe. # Punkte und wird zum KEGEL. Breit + genug Punkte = runde Kuppe.
@@ -223,17 +220,23 @@ def build_group():
rt = N("ShaderNodeMath"); rt.location = (x + 300, y); rt.operation = 'POWER' rt = N("ShaderNodeMath"); rt.location = (x + 300, y); rt.operation = 'POWER'
rt.inputs[1].default_value = 0.5 rt.inputs[1].default_value = 0.5
L(s.outputs[0], rt.inputs[0]) L(s.outputs[0], rt.inputs[0])
# Radius NIE auf 0 laufen lassen: sonst entsteht immer eine Spitze, return rt
# egal wie fein resampled wird. Mit Mindestradius + Fill Caps endet
# der Arm stumpf/gerundet statt als Dorn. # Verjuengung UND Kuppel GEMEINSAM begrenzen, dann erst mit dem Basisradius
mx = N("ShaderNodeMath"); mx.location = (x + 450, y); mx.operation = 'MAXIMUM' # multiplizieren. Wirkt der Mindestwert nur auf die Kuppel, bleibt der bereits
L(rt.outputs[0], mx.inputs[0]) # verjuengte Radius trotzdem winzig — gemessen: Sub-Ast-Spitze 0.8 mm bei
L(V["Tip Blunt"], mx.inputs[1]) # 31 mm Basis, also weiterhin eine Nadel.
return mx def _shape(inv_taper_socket, dome_node, base_socket, x, y):
mul = N("ShaderNodeMath"); mul.location = (x, y); mul.operation = 'MULTIPLY'
L(inv_taper_socket, mul.inputs[0]); L(dome_node.outputs[0], mul.inputs[1])
mx = N("ShaderNodeMath"); mx.location = (x + 150, y); mx.operation = 'MAXIMUM'
L(mul.outputs[0], mx.inputs[0]); L(V["Tip Blunt"], mx.inputs[1])
r = N("ShaderNodeMath"); r.location = (x + 300, y); r.operation = 'MULTIPLY'
L(base_socket, r.inputs[0]); L(mx.outputs[0], r.inputs[1])
return r
tdome = _dome(spar, -900, 220) tdome = _dome(spar, -900, 220)
trad = N("ShaderNodeMath"); trad.location = (-100, 60); trad.operation = 'MULTIPLY' trad = _shape(inv.outputs[0], tdome, V["Trunk Radius"], -260, 60)
L(trad0.outputs[0], trad.inputs[0]); L(tdome.outputs[0], trad.inputs[1])
setrad = N("GeometryNodeSetCurveRadius"); setrad.location = (-80, 200) setrad = N("GeometryNodeSetCurveRadius"); setrad.location = (-80, 200)
L(_out(setpos, "Geometry"), _sock(setrad, "Curve")) L(_out(setpos, "Geometry"), _sock(setrad, "Curve"))
@@ -275,16 +278,12 @@ def build_group():
binv = N("ShaderNodeMath"); binv.location = (440, -140) binv = N("ShaderNodeMath"); binv.location = (440, -140)
binv.operation = 'SUBTRACT'; binv.inputs[0].default_value = 1.0 binv.operation = 'SUBTRACT'; binv.inputs[0].default_value = 1.0
L(btap.outputs[0], binv.inputs[1]) L(btap.outputs[0], binv.inputs[1])
bmul = N("ShaderNodeMath"); bmul.location = (600, -140); bmul.operation = 'MULTIPLY'
L(V["Trunk Radius"], bmul.inputs[0]); L(binv.outputs[0], bmul.inputs[1])
# Ast-Dicke relativ zum Stamm. Beim Kaktus muessen die Arme fast so dick # Ast-Dicke relativ zum Stamm. Beim Kaktus muessen die Arme fast so dick
# sein wie der Stamm (0.7+), beim Baum deutlich duenner (~0.3). # sein wie der Stamm (0.7+), beim Baum deutlich duenner (~0.3).
bscl0 = N("ShaderNodeMath"); bscl0.location = (760, -140); bscl0.operation = 'MULTIPLY' bbase = N("ShaderNodeMath"); bbase.location = (600, -140); bbase.operation = 'MULTIPLY'
L(bmul.outputs[0], bscl0.inputs[0]) L(V["Trunk Radius"], bbase.inputs[0]); L(V["Branch Thickness"], bbase.inputs[1])
L(V["Branch Thickness"], bscl0.inputs[1])
bdome = _dome(bspar, 600, -600) bdome = _dome(bspar, 600, -600)
bscl = N("ShaderNodeMath"); bscl.location = (1080, -140); bscl.operation = 'MULTIPLY' bscl = _shape(binv.outputs[0], bdome, bbase.outputs[0], 780, -140)
L(bscl0.outputs[0], bscl.inputs[0]); L(bdome.outputs[0], bscl.inputs[1])
bsetr = N("GeometryNodeSetCurveRadius"); bsetr.location = (600, 40) bsetr = N("GeometryNodeSetCurveRadius"); bsetr.location = (600, 40)
L(_out(bres, "Curve"), _sock(bsetr, "Curve")) L(_out(bres, "Curve"), _sock(bsetr, "Curve"))
@@ -415,14 +414,11 @@ def build_group():
sinv = N("ShaderNodeMath"); sinv.location = (2400, 900) sinv = N("ShaderNodeMath"); sinv.location = (2400, 900)
sinv.operation = 'SUBTRACT'; sinv.inputs[0].default_value = 1.0 sinv.operation = 'SUBTRACT'; sinv.inputs[0].default_value = 1.0
L(stap.outputs[0], sinv.inputs[1]) L(stap.outputs[0], sinv.inputs[1])
srad = N("ShaderNodeMath"); srad.location = (2550, 900); srad.operation = 'MULTIPLY' sbase = N("ShaderNodeMath"); sbase.location = (2550, 900); sbase.operation = 'MULTIPLY'
L(V["Trunk Radius"], srad.inputs[0]); L(sinv.outputs[0], srad.inputs[1]) L(V["Trunk Radius"], sbase.inputs[0])
srad1 = N("ShaderNodeMath"); srad1.location = (2700, 900); srad1.operation = 'MULTIPLY' sbase.inputs[1].default_value = 0.32 # duenner als Hauptaeste, aber keine Nadel
srad1.inputs[1].default_value = 0.24 # duenner als Hauptaeste
L(srad.outputs[0], srad1.inputs[0])
sdome = _dome(sspar, 2550, 1200) sdome = _dome(sspar, 2550, 1200)
srad2 = N("ShaderNodeMath"); srad2.location = (3050, 900); srad2.operation = 'MULTIPLY' srad2 = _shape(sinv.outputs[0], sdome, sbase.outputs[0], 2750, 900)
L(srad1.outputs[0], srad2.inputs[0]); L(sdome.outputs[0], srad2.inputs[1])
ssetr = N("GeometryNodeSetCurveRadius"); ssetr.location = (2550, 760) ssetr = N("GeometryNodeSetCurveRadius"); ssetr.location = (2550, 760)
L(_out(sres, "Curve"), _sock(ssetr, "Curve")) L(_out(sres, "Curve"), _sock(ssetr, "Curve"))
L(srad2.outputs[0], _sock(ssetr, "Radius")) L(srad2.outputs[0], _sock(ssetr, "Radius"))