Tree Generator v1.4.0: Zweige gebogen wie der Stamm
Sub-Aeste hatten gar keine Biegung -> gerade Staebe. Jetzt nutzen Stamm, Aeste und Zweige dieselbe Noise-Kruemmung (nach Realize ueber die Weltposition, damit jeder Zweig anders faellt). Zweige ausserdem duenn + fast gleichmaessig statt dick-kegelig (das war die eigentliche Dorn-Ursache). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
bl_info = {
|
||||
"name": "Stylized Tree Generator",
|
||||
"author": "D4rkst3r",
|
||||
"version": (1, 3, 0),
|
||||
"version": (1, 4, 0),
|
||||
"blender": (4, 2, 0),
|
||||
"location": "View3D > Sidebar > Tree Gen",
|
||||
"description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen",
|
||||
@@ -36,10 +36,10 @@ DEFAULTS = {
|
||||
"Branch Up": 1.3, # >1 = Aeste zeigen nach oben; negativ = haengend
|
||||
"Branch Start": 0.35, # ab wo am Stamm Aeste sitzen (0..1)
|
||||
"Branch End": 0.95,
|
||||
"Branch Bend": 0.45, # Variation je Ast (0 = gerade Staebe)
|
||||
"Branch Bend": 0.75, # Krummheit je Ast/Zweig (0 = gerade Staebe)
|
||||
"Branch Droop": 0.0, # >0 haengt nach unten (Palme), <0 kruemmt nach oben (Kaktus)
|
||||
"Branch Thickness": 0.32, # Ast-Dicke relativ zum Stamm
|
||||
"Branch Taper": 0.85, # wie der Stamm: laeuft NICHT auf 0 -> keine Nadeln
|
||||
"Branch Taper": 0.55, # schwach verjuengen -> Roehre statt Kegel/Dorn
|
||||
"Sub Count": 3, # Sub-Aeste je Hauptast (0 = aus)
|
||||
"Sub Length": 0.55,
|
||||
"Sub Up": 1.4,
|
||||
@@ -403,20 +403,24 @@ def build_group():
|
||||
L(V["Sub Length"], stop.inputs["Z"])
|
||||
L(stop.outputs[0], _sock(sline, "End"))
|
||||
sres = N("GeometryNodeResampleCurve"); sres.location = (2250, 760)
|
||||
_sock(sres, "Count").default_value = 6
|
||||
_sock(sres, "Count").default_value = 9 # genug Punkte, damit die Biegung sichtbar wird
|
||||
L(_out(sline, "Curve"), _sock(sres, "Curve"))
|
||||
|
||||
# Sub-Aeste: gleiche Verjuengungs-Logik wie Hauptaeste (Branch Taper + Kuppel).
|
||||
# Vorher lief der Radius hier hart auf 0 -> die Sub-Aeste wurden zu Nadeln.
|
||||
sspar = N("GeometryNodeSplineParameter"); sspar.location = (2250, 900)
|
||||
# ... und verjuengen sich nur SCHWACH. Ein dicker Ansatz, der spitz zulaeuft,
|
||||
# ist genau die Dorn-Form - ein echter Zweig ist duenn und gleichmaessig.
|
||||
shalf = N("ShaderNodeMath"); shalf.location = (2180, 1000); shalf.operation = 'MULTIPLY'
|
||||
L(V["Branch Taper"], shalf.inputs[0]); shalf.inputs[1].default_value = 0.35
|
||||
stap = N("ShaderNodeMath"); stap.location = (2330, 1000); stap.operation = 'MULTIPLY'
|
||||
L(V["Branch Taper"], stap.inputs[0]); L(sspar.outputs["Factor"], stap.inputs[1])
|
||||
L(shalf.outputs[0], stap.inputs[0]); L(sspar.outputs["Factor"], stap.inputs[1])
|
||||
sinv = N("ShaderNodeMath"); sinv.location = (2400, 900)
|
||||
sinv.operation = 'SUBTRACT'; sinv.inputs[0].default_value = 1.0
|
||||
L(stap.outputs[0], sinv.inputs[1])
|
||||
sbase = N("ShaderNodeMath"); sbase.location = (2550, 900); sbase.operation = 'MULTIPLY'
|
||||
L(V["Trunk Radius"], sbase.inputs[0])
|
||||
sbase.inputs[1].default_value = 0.32 # duenner als Hauptaeste, aber keine Nadel
|
||||
sbase.inputs[1].default_value = 0.12 # Zweige sind DUENN ...
|
||||
sdome = _dome(sspar, 2550, 1200)
|
||||
srad2 = _shape(sinv.outputs[0], sdome, sbase.outputs[0], 2750, 900)
|
||||
ssetr = N("GeometryNodeSetCurveRadius"); ssetr.location = (2550, 760)
|
||||
@@ -443,8 +447,36 @@ def build_group():
|
||||
sreal = N("GeometryNodeRealizeInstances"); sreal.location = (3000, 520)
|
||||
L(_out(sinst, "Instances", "Geometry"), _sock(sreal, "Geometry"))
|
||||
|
||||
# Sub-Aeste genauso biegen wie Stamm und Hauptaeste. Ohne diesen Schritt
|
||||
# blieben sie schnurgerade - das ist der Grund, warum sie wie angeklebte
|
||||
# Staebe wirkten. Auch hier NACH dem Realize, damit die Weltposition jedem
|
||||
# Zweig ein eigenes Noise gibt (sonst biegen alle identisch).
|
||||
sbspar = N("GeometryNodeSplineParameter"); sbspar.location = (3000, 300)
|
||||
sbpos = N("GeometryNodeInputPosition"); sbpos.location = (3000, 160)
|
||||
sbnoise = N("ShaderNodeTexNoise"); sbnoise.location = (3150, 160)
|
||||
sbnoise.noise_dimensions = '4D'
|
||||
_sock(sbnoise, "Scale").default_value = 1.6
|
||||
L(sbpos.outputs[0], _sock(sbnoise, "Vector"))
|
||||
L(V["Seed"], _sock(sbnoise, "W"))
|
||||
sbsub = N("ShaderNodeVectorMath"); sbsub.location = (3320, 160)
|
||||
sbsub.operation = 'SUBTRACT'; sbsub.inputs[1].default_value = (0.5, 0.5, 0.5)
|
||||
L(sbnoise.outputs["Color"], sbsub.inputs[0])
|
||||
sbfac = N("ShaderNodeMath"); sbfac.location = (3150, 300); sbfac.operation = 'MULTIPLY'
|
||||
L(V["Branch Bend"], sbfac.inputs[0])
|
||||
L(sbspar.outputs["Factor"], sbfac.inputs[1])
|
||||
sbamt = N("ShaderNodeMath"); sbamt.location = (3320, 300); sbamt.operation = 'MULTIPLY'
|
||||
sbamt.inputs[1].default_value = 0.5 # Zweige biegen etwas weniger als Aeste
|
||||
L(sbfac.outputs[0], sbamt.inputs[0])
|
||||
sboff = N("ShaderNodeVectorMath"); sboff.location = (3480, 220)
|
||||
sboff.operation = 'SCALE'
|
||||
L(sbsub.outputs[0], sboff.inputs[0])
|
||||
L(sbamt.outputs[0], _sock(sboff, "Scale"))
|
||||
sbset = N("GeometryNodeSetPosition"); sbset.location = (3640, 520)
|
||||
L(_out(sreal, "Geometry"), _sock(sbset, "Geometry"))
|
||||
L(sboff.outputs[0], _sock(sbset, "Offset"))
|
||||
|
||||
join = N("GeometryNodeJoinGeometry"); join.location = (3150, 200)
|
||||
L(_out(sreal, "Geometry"), join.inputs[0])
|
||||
L(_out(sbset, "Geometry"), join.inputs[0])
|
||||
L(_out(rsetp, "Geometry"), join.inputs[0])
|
||||
L(_out(setrad, "Curve"), join.inputs[0])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user