Tree Generator v1.7.0: Tri-Budget, Detail-Regler, Wurzelanlauf
- 'Detail' skaliert alle Resample-Counts -> zentrale Budget-Stellschraube - Defaults treffen jetzt das Projekt-Budget (baum 1368, busch 532 Tris) - 'Root Flare': Wurzelanlauf am Stammfuss, kostet keine Tris Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
schema_version = "1.0.0"
|
||||
|
||||
id = "stylized_tree_generator"
|
||||
version = "1.6.0"
|
||||
version = "1.7.0"
|
||||
name = "Stylized Tree Generator"
|
||||
tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen"
|
||||
maintainer = "D4rkst3r"
|
||||
|
||||
Vendored
+4
-4
@@ -32,7 +32,7 @@
|
||||
"id": "stylized_tree_generator",
|
||||
"name": "Stylized Tree Generator",
|
||||
"tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"type": "add-on",
|
||||
"maintainer": "D4rkst3r",
|
||||
"license": [
|
||||
@@ -48,9 +48,9 @@
|
||||
"Mesh",
|
||||
"Modeling"
|
||||
],
|
||||
"archive_url": "./stylized_tree_generator-1.6.0.zip",
|
||||
"archive_size": 12916,
|
||||
"archive_hash": "sha256:48d7072d65d44c944fe7dd160147f37f496132d6c2583c5251f0d6aba499476b"
|
||||
"archive_url": "./stylized_tree_generator-1.7.0.zip",
|
||||
"archive_size": 13398,
|
||||
"archive_hash": "sha256:3817ce7433ef63918ddf75a827591b3bb712c8659141ae85f73f4f1fd19e20fb"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
bl_info = {
|
||||
"name": "Stylized Tree Generator",
|
||||
"author": "D4rkst3r",
|
||||
"version": (1, 6, 0),
|
||||
"version": (1, 7, 0),
|
||||
"blender": (4, 2, 0),
|
||||
"location": "View3D > Sidebar > Tree Gen",
|
||||
"description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen",
|
||||
@@ -40,12 +40,14 @@ DEFAULTS = {
|
||||
"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.55, # schwach verjuengen -> Roehre statt Kegel/Dorn
|
||||
"Sub Count": 3, # Sub-Aeste je Hauptast (0 = aus)
|
||||
"Sub Count": 2, # Sub-Aeste je Hauptast (0 = aus)
|
||||
"Sub Length": 0.55,
|
||||
"Sub Up": 1.4,
|
||||
"Sides": 6,
|
||||
"Sides": 5,
|
||||
"UV Scale": 1.0, # Rinden-Dichte; UVs sind world-space (m)
|
||||
"Tip Blunt": 0.18, # >0 verhindert Nadelspitzen (0 = spitz, 0.45 = Kaktus)
|
||||
"Root Flare": 1.1, # Wurzelanlauf: Stamm verbreitert sich am Fuss
|
||||
"Detail": 0.55, # skaliert alle Resample-Counts = Tri-Budget-Regler
|
||||
"Branch Collar": 0.4, # Ansatz-Verdickung: Uebergang Ast->Stamm (0 = aus)
|
||||
"Merge": 0.0, # 1 = Aeste per Voxel-Remesh mit dem Stamm verschmelzen
|
||||
"Merge Voxel": 0.03, # Voxelgroesse (m): klein = feiner, aber teuer
|
||||
@@ -69,7 +71,8 @@ PRESETS = {
|
||||
"Branch Count": 14, "Branch Length": 0.9, "Branch Up": 1.0,
|
||||
"Branch Start": 0.15, "Branch End": 0.95,
|
||||
"Branch Bend": 0.6, "Branch Droop": 0.0,
|
||||
"Sub Count": 2, "Sub Length": 0.35, "Sub Up": 1.6, "Sides": 5,
|
||||
"Sub Count": 1, "Sub Length": 0.35, "Sub Up": 1.6, "Sides": 4,
|
||||
"Detail": 0.3, "Branch Count": 10,
|
||||
},
|
||||
# Kaktus: dicker, kaum verjuengter Stamm, wenige Arme, die per NEGATIVEM
|
||||
# Droop nach oben kruemmen (Saguaro-Silhouette). Keine Sub-Aeste.
|
||||
@@ -112,6 +115,18 @@ def build_group():
|
||||
N, L = ng.nodes.new, ng.links.new
|
||||
iface = ng.interface
|
||||
|
||||
def _count(base, x, y):
|
||||
"""Resample-Count = base * Detail, mindestens 3. Der zentrale
|
||||
Tri-Budget-Regler: die Segmentzahl entlang der Kurven dominiert die
|
||||
Dreiecke (Tris ~ Segmente * Sides * 2)."""
|
||||
mul = N("ShaderNodeMath"); mul.location = (x, y); mul.operation = 'MULTIPLY'
|
||||
mul.inputs[0].default_value = float(base)
|
||||
L(V["Detail"], mul.inputs[1])
|
||||
mx = N("ShaderNodeMath"); mx.location = (x + 150, y); mx.operation = 'MAXIMUM'
|
||||
mx.inputs[1].default_value = 3.0
|
||||
L(mul.outputs[0], mx.inputs[0])
|
||||
return mx
|
||||
|
||||
def _new_any(*bl_idnames):
|
||||
"""Falle 2: erster Node-Typ, den diese Blender-Version kennt."""
|
||||
for bid in bl_idnames:
|
||||
@@ -153,6 +168,8 @@ def build_group():
|
||||
add_in("Sides", 'NodeSocketInt', DEFAULTS["Sides"], 3, 32)
|
||||
add_in("Tip Blunt", 'NodeSocketFloat', DEFAULTS["Tip Blunt"], 0.0, 0.9)
|
||||
add_in("UV Scale", 'NodeSocketFloat', DEFAULTS["UV Scale"], 0.01, 20.0)
|
||||
add_in("Detail", 'NodeSocketFloat', DEFAULTS["Detail"], 0.2, 2.0)
|
||||
add_in("Root Flare", 'NodeSocketFloat', DEFAULTS["Root Flare"], 0.0, 4.0)
|
||||
add_in("Branch Collar", 'NodeSocketFloat', DEFAULTS["Branch Collar"], 0.0, 3.0)
|
||||
add_in("Merge", 'NodeSocketFloat', DEFAULTS["Merge"], 0.0, 1.0)
|
||||
add_in("Merge Voxel", 'NodeSocketFloat', DEFAULTS["Merge Voxel"], 0.005, 0.2)
|
||||
@@ -170,7 +187,7 @@ def build_group():
|
||||
L(top.outputs[0], _sock(line, "End"))
|
||||
|
||||
res = N("GeometryNodeResampleCurve"); res.location = (-950, 200)
|
||||
_sock(res, "Count").default_value = 24 # genug Punkte, damit die Kuppel rund wird
|
||||
L(_count(24, -1150, 380).outputs[0], _sock(res, "Count"))
|
||||
L(_out(line, "Curve"), _sock(res, "Curve"))
|
||||
|
||||
spar = N("GeometryNodeSplineParameter"); spar.location = (-950, -60)
|
||||
@@ -270,8 +287,25 @@ def build_group():
|
||||
L(inv.outputs[0], tmulr.inputs[0]); L(tdome.outputs[0], tmulr.inputs[1])
|
||||
tmaxr = N("ShaderNodeMath"); tmaxr.location = (-110, 60); tmaxr.operation = 'MAXIMUM'
|
||||
L(tmulr.outputs[0], tmaxr.inputs[0]); L(ttip.outputs[0], tmaxr.inputs[1])
|
||||
trad = N("ShaderNodeMath"); trad.location = (40, 60); trad.operation = 'MULTIPLY'
|
||||
L(V["Trunk Radius"], trad.inputs[0]); L(tmaxr.outputs[0], trad.inputs[1])
|
||||
|
||||
# Wurzelanlauf: der Stamm verbreitert sich am Fuss. Hoher Exponent -> nur
|
||||
# das unterste Stueck ist betroffen. Kostet keine Tris, nur Radius.
|
||||
rfi = N("ShaderNodeMath"); rfi.location = (-420, -220); rfi.operation = 'SUBTRACT'
|
||||
rfi.inputs[0].default_value = 1.0
|
||||
L(spar.outputs["Factor"], rfi.inputs[1])
|
||||
rfp = N("ShaderNodeMath"); rfp.location = (-270, -220); rfp.operation = 'POWER'
|
||||
rfp.inputs[1].default_value = 9.0
|
||||
L(rfi.outputs[0], rfp.inputs[0])
|
||||
rfm = N("ShaderNodeMath"); rfm.location = (-120, -220); rfm.operation = 'MULTIPLY'
|
||||
L(V["Root Flare"], rfm.inputs[0]); L(rfp.outputs[0], rfm.inputs[1])
|
||||
rfa = N("ShaderNodeMath"); rfa.location = (30, -220); rfa.operation = 'ADD'
|
||||
rfa.inputs[0].default_value = 1.0
|
||||
L(rfm.outputs[0], rfa.inputs[1])
|
||||
tflare = N("ShaderNodeMath"); tflare.location = (30, -60); tflare.operation = 'MULTIPLY'
|
||||
L(tmaxr.outputs[0], tflare.inputs[0]); L(rfa.outputs[0], tflare.inputs[1])
|
||||
|
||||
trad = N("ShaderNodeMath"); trad.location = (190, 60); trad.operation = 'MULTIPLY'
|
||||
L(V["Trunk Radius"], trad.inputs[0]); L(tflare.outputs[0], trad.inputs[1])
|
||||
|
||||
setrad = N("GeometryNodeSetCurveRadius"); setrad.location = (-80, 200)
|
||||
L(_out(setpos, "Geometry"), _sock(setrad, "Curve"))
|
||||
@@ -301,7 +335,7 @@ def build_group():
|
||||
L(V["Branch Length"], btop.inputs["Z"])
|
||||
L(btop.outputs[0], _sock(bline, "End"))
|
||||
bres = N("GeometryNodeResampleCurve"); bres.location = (280, 40)
|
||||
_sock(bres, "Count").default_value = 14 # zu wenig -> Kuppel wird zum Kegel
|
||||
L(_count(14, 100, 200).outputs[0], _sock(bres, "Count"))
|
||||
L(_out(bline, "Curve"), _sock(bres, "Curve"))
|
||||
|
||||
# Ast-Verjuengung: 1 - BranchTaper*factor. Bei Kakteen klein halten,
|
||||
@@ -453,7 +487,7 @@ 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 = 9 # genug Punkte, damit die Biegung sichtbar wird
|
||||
L(_count(9, 2100, 700).outputs[0], _sock(sres, "Count"))
|
||||
L(_out(sline, "Curve"), _sock(sres, "Curve"))
|
||||
|
||||
# Sub-Aeste: gleiche Verjuengungs-Logik wie Hauptaeste (Branch Taper + Kuppel).
|
||||
|
||||
Reference in New Issue
Block a user