Tree Generator v1.9.0: Wurzelbretter am Stammfuss
Gelappter Wurzelanlauf statt glattem Trichter (Root Lobes / Root Lobe Depth / Root Height). Als Mesh-Offset umgesetzt -> 0 zusaetzliche Tris. Stamm-Sides auf 12 fuer saubere Lappen (+104 Tris, gemessen). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
schema_version = "1.0.0"
|
schema_version = "1.0.0"
|
||||||
|
|
||||||
id = "stylized_tree_generator"
|
id = "stylized_tree_generator"
|
||||||
version = "1.8.0"
|
version = "1.9.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"
|
||||||
|
|||||||
Vendored
+4
-4
@@ -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.8.0",
|
"version": "1.9.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.8.0.zip",
|
"archive_url": "./stylized_tree_generator-1.9.0.zip",
|
||||||
"archive_size": 13440,
|
"archive_size": 14478,
|
||||||
"archive_hash": "sha256:e96e6ec6f8009708ce0611dea6ea50e3271b6603d60bce84ebeab2e365bba983"
|
"archive_hash": "sha256:07c964096cd907dab9e22e1bc936621ed25476e188ebaa6176a18e98c5f76a4c"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -1,7 +1,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Stylized Tree Generator",
|
"name": "Stylized Tree Generator",
|
||||||
"author": "D4rkst3r",
|
"author": "D4rkst3r",
|
||||||
"version": (1, 8, 0),
|
"version": (1, 9, 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",
|
||||||
@@ -43,12 +43,18 @@ DEFAULTS = {
|
|||||||
"Sub Count": 2, # Sub-Aeste je Hauptast (0 = aus)
|
"Sub Count": 2, # Sub-Aeste je Hauptast (0 = aus)
|
||||||
"Sub Length": 0.55,
|
"Sub Length": 0.55,
|
||||||
"Sub Up": 1.4,
|
"Sub Up": 1.4,
|
||||||
"Sides": 8, # Stamm rund (Referenz TreeIt: ~9)
|
"Sides": 12, # Stamm rund genug fuer die Wurzelbretter
|
||||||
|
# (+104 Tris ggue. 8 - gemessen, lohnt sich)
|
||||||
"Branch Sides": 4, # Aeste sparsamer
|
"Branch Sides": 4, # Aeste sparsamer
|
||||||
"Sub Sides": 3, # Zweige nur Dreiecke - sieht man nicht
|
"Sub Sides": 3, # Zweige nur Dreiecke - sieht man nicht
|
||||||
"UV Scale": 1.0, # Rinden-Dichte; UVs sind world-space (m)
|
"UV Scale": 1.0, # Rinden-Dichte; UVs sind world-space (m)
|
||||||
"Tip Blunt": 0.18, # >0 verhindert Nadelspitzen (0 = spitz, 0.45 = Kaktus)
|
"Tip Blunt": 0.18, # >0 verhindert Nadelspitzen (0 = spitz, 0.45 = Kaktus)
|
||||||
"Root Flare": 1.1, # Wurzelanlauf: Stamm verbreitert sich am Fuss
|
"Root Flare": 1.1, # Wurzelanlauf: Stamm verbreitert sich am Fuss
|
||||||
|
"Root Lobes": 6.0, # Wurzelbretter; sollte in "Sides" aufgehen,
|
||||||
|
# sonst sampelt das Profil die Lappen weg
|
||||||
|
"Root Lobe Depth": 1.3, # wie weit die Lappen rausstehen
|
||||||
|
"Root Height": 1.1, # Hoehe (m) des Anlaufs; zu klein -> zu wenige
|
||||||
|
# Ringe liegen drin und man sieht nichts
|
||||||
"Detail": 0.55, # skaliert alle Resample-Counts = Tri-Budget-Regler
|
"Detail": 0.55, # skaliert alle Resample-Counts = Tri-Budget-Regler
|
||||||
"Branch Collar": 0.4, # Ansatz-Verdickung: Uebergang Ast->Stamm (0 = aus)
|
"Branch Collar": 0.4, # Ansatz-Verdickung: Uebergang Ast->Stamm (0 = aus)
|
||||||
"Merge": 0.0, # 1 = Aeste per Voxel-Remesh mit dem Stamm verschmelzen
|
"Merge": 0.0, # 1 = Aeste per Voxel-Remesh mit dem Stamm verschmelzen
|
||||||
@@ -174,6 +180,9 @@ def build_group():
|
|||||||
add_in("UV Scale", 'NodeSocketFloat', DEFAULTS["UV Scale"], 0.01, 20.0)
|
add_in("UV Scale", 'NodeSocketFloat', DEFAULTS["UV Scale"], 0.01, 20.0)
|
||||||
add_in("Detail", 'NodeSocketFloat', DEFAULTS["Detail"], 0.2, 2.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("Root Flare", 'NodeSocketFloat', DEFAULTS["Root Flare"], 0.0, 4.0)
|
||||||
|
add_in("Root Lobes", 'NodeSocketFloat', DEFAULTS["Root Lobes"], 0.0, 12.0)
|
||||||
|
add_in("Root Lobe Depth", 'NodeSocketFloat', DEFAULTS["Root Lobe Depth"], 0.0, 3.0)
|
||||||
|
add_in("Root Height", 'NodeSocketFloat', DEFAULTS["Root Height"], 0.05, 3.0)
|
||||||
add_in("Branch Collar", 'NodeSocketFloat', DEFAULTS["Branch Collar"], 0.0, 3.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", 'NodeSocketFloat', DEFAULTS["Merge"], 0.0, 1.0)
|
||||||
add_in("Merge Voxel", 'NodeSocketFloat', DEFAULTS["Merge Voxel"], 0.005, 0.2)
|
add_in("Merge Voxel", 'NodeSocketFloat', DEFAULTS["Merge Voxel"], 0.005, 0.2)
|
||||||
@@ -664,7 +673,63 @@ def build_group():
|
|||||||
L(uv.outputs[0], _sock(sm, "Value"))
|
L(uv.outputs[0], _sock(sm, "Value"))
|
||||||
return sm
|
return sm
|
||||||
|
|
||||||
mesh_trunk = _to_mesh(setrad, "Curve", V["Sides"], 3400, 900)
|
mesh_trunk0 = _to_mesh(setrad, "Curve", V["Sides"], 3400, 900)
|
||||||
|
|
||||||
|
# ---------- Wurzelanlauf ausformen (Wurzelbretter) ----------
|
||||||
|
# Der reine Radius-Flare ergibt einen glatten Trichter. Echte Wurzelanlaeufe
|
||||||
|
# sind GELAPPT. Das laesst sich nicht ueber den Kurvenradius machen (der ist
|
||||||
|
# rundum gleich), sondern erst am fertigen Mesh: Vertices nahe dem Boden
|
||||||
|
# radial nach aussen schieben, moduliert ueber den Winkel. Kostet 0 Tris.
|
||||||
|
fpos = N("GeometryNodeInputPosition"); fpos.location = (4750, 1150)
|
||||||
|
fsep = N("ShaderNodeSeparateXYZ"); fsep.location = (4900, 1150)
|
||||||
|
L(fpos.outputs[0], fsep.inputs[0])
|
||||||
|
|
||||||
|
# Hoehen-Abfall: nur das unterste Stueck ist betroffen
|
||||||
|
fh = N("ShaderNodeMath"); fh.location = (5050, 1300); fh.operation = 'DIVIDE'
|
||||||
|
L(fsep.outputs["Z"], fh.inputs[0]); L(V["Root Height"], fh.inputs[1])
|
||||||
|
fc = N("ShaderNodeMath"); fc.location = (5200, 1300); fc.operation = 'MINIMUM'
|
||||||
|
fc.inputs[1].default_value = 1.0
|
||||||
|
L(fh.outputs[0], fc.inputs[0])
|
||||||
|
fi = N("ShaderNodeMath"); fi.location = (5350, 1300); fi.operation = 'SUBTRACT'
|
||||||
|
fi.inputs[0].default_value = 1.0
|
||||||
|
L(fc.outputs[0], fi.inputs[1])
|
||||||
|
fp = N("ShaderNodeMath"); fp.location = (5500, 1300); fp.operation = 'POWER'
|
||||||
|
fp.inputs[1].default_value = 2.5
|
||||||
|
L(fi.outputs[0], fp.inputs[0])
|
||||||
|
fpc = N("ShaderNodeMath"); fpc.location = (5650, 1300); fpc.operation = 'MAXIMUM'
|
||||||
|
fpc.inputs[1].default_value = 0.0
|
||||||
|
L(fp.outputs[0], fpc.inputs[0])
|
||||||
|
|
||||||
|
# Lappen ueber den Winkel: cos(Lobes * atan2(y,x)), auf 0..1 gehoben
|
||||||
|
fat = N("ShaderNodeMath"); fat.location = (5050, 1000); fat.operation = 'ARCTAN2'
|
||||||
|
L(fsep.outputs["Y"], fat.inputs[0]); L(fsep.outputs["X"], fat.inputs[1])
|
||||||
|
fml = N("ShaderNodeMath"); fml.location = (5200, 1000); fml.operation = 'MULTIPLY'
|
||||||
|
L(fat.outputs[0], fml.inputs[0]); L(V["Root Lobes"], fml.inputs[1])
|
||||||
|
fco = N("ShaderNodeMath"); fco.location = (5350, 1000); fco.operation = 'COSINE'
|
||||||
|
L(fml.outputs[0], fco.inputs[0])
|
||||||
|
fno = N("ShaderNodeMath"); fno.location = (5500, 1000); fno.operation = 'MULTIPLY_ADD'
|
||||||
|
fno.inputs[1].default_value = 0.5; fno.inputs[2].default_value = 0.5
|
||||||
|
L(fco.outputs[0], fno.inputs[0])
|
||||||
|
|
||||||
|
# Betrag = RootLobeDepth * Hoehenabfall * Lappen * Stammradius
|
||||||
|
fa1 = N("ShaderNodeMath"); fa1.location = (5800, 1150); fa1.operation = 'MULTIPLY'
|
||||||
|
L(fpc.outputs[0], fa1.inputs[0]); L(fno.outputs[0], fa1.inputs[1])
|
||||||
|
fa2 = N("ShaderNodeMath"); fa2.location = (5950, 1150); fa2.operation = 'MULTIPLY'
|
||||||
|
L(fa1.outputs[0], fa2.inputs[0]); L(V["Root Lobe Depth"], fa2.inputs[1])
|
||||||
|
fa3 = N("ShaderNodeMath"); fa3.location = (6100, 1150); fa3.operation = 'MULTIPLY'
|
||||||
|
L(fa2.outputs[0], fa3.inputs[0]); L(V["Trunk Radius"], fa3.inputs[1])
|
||||||
|
|
||||||
|
# Richtung: radial nach aussen (XY), Z bleibt unangetastet
|
||||||
|
fxy = N("ShaderNodeCombineXYZ"); fxy.location = (5200, 850)
|
||||||
|
L(fsep.outputs["X"], fxy.inputs["X"]); L(fsep.outputs["Y"], fxy.inputs["Y"])
|
||||||
|
fnrm = N("ShaderNodeVectorMath"); fnrm.location = (5350, 850); fnrm.operation = 'NORMALIZE'
|
||||||
|
L(fxy.outputs[0], fnrm.inputs[0])
|
||||||
|
foff = N("ShaderNodeVectorMath"); foff.location = (6250, 1000); foff.operation = 'SCALE'
|
||||||
|
L(fnrm.outputs[0], foff.inputs[0]); L(fa3.outputs[0], _sock(foff, "Scale"))
|
||||||
|
|
||||||
|
mesh_trunk = N("GeometryNodeSetPosition"); mesh_trunk.location = (6400, 900)
|
||||||
|
L(_out(mesh_trunk0, "Geometry"), _sock(mesh_trunk, "Geometry"))
|
||||||
|
L(foff.outputs[0], _sock(mesh_trunk, "Offset"))
|
||||||
mesh_branch = _to_mesh(rsetp, "Geometry", V["Branch Sides"], 3400, 200)
|
mesh_branch = _to_mesh(rsetp, "Geometry", V["Branch Sides"], 3400, 200)
|
||||||
mesh_sub = _to_mesh(sbset, "Geometry", V["Sub Sides"], 3400, -500)
|
mesh_sub = _to_mesh(sbset, "Geometry", V["Sub Sides"], 3400, -500)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user