diff --git a/blender_manifest_tree.toml b/blender_manifest_tree.toml index 9b7a147..5b5be0b 100644 --- a/blender_manifest_tree.toml +++ b/blender_manifest_tree.toml @@ -1,7 +1,7 @@ schema_version = "1.0.0" id = "stylized_tree_generator" -version = "1.2.0" +version = "1.3.0" name = "Stylized Tree Generator" tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen" maintainer = "D4rkst3r" diff --git a/dist/index.json b/dist/index.json index bbb73f9..479b63d 100644 --- a/dist/index.json +++ b/dist/index.json @@ -32,7 +32,7 @@ "id": "stylized_tree_generator", "name": "Stylized Tree Generator", "tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen", - "version": "1.2.0", + "version": "1.3.0", "type": "add-on", "maintainer": "D4rkst3r", "license": [ @@ -48,9 +48,9 @@ "Mesh", "Modeling" ], - "archive_url": "./stylized_tree_generator-1.2.0.zip", - "archive_size": 10862, - "archive_hash": "sha256:8297d75cf7b8d73189471b480f65e98861ee73840f0ab387fb9f2141fa80a083" + "archive_url": "./stylized_tree_generator-1.3.0.zip", + "archive_size": 10852, + "archive_hash": "sha256:31c7a72133a6c28d24f95d661cabf0be56dc00c3102ad57a4a3c1e1c5a30bcd4" } ] } \ No newline at end of file diff --git a/dist/stylized_tree_generator-1.2.0.zip b/dist/stylized_tree_generator-1.2.0.zip deleted file mode 100644 index 1947b97..0000000 Binary files a/dist/stylized_tree_generator-1.2.0.zip and /dev/null differ diff --git a/dist/stylized_tree_generator-1.3.0.zip b/dist/stylized_tree_generator-1.3.0.zip new file mode 100644 index 0000000..5d0dc28 Binary files /dev/null and b/dist/stylized_tree_generator-1.3.0.zip differ diff --git a/stylized_tree_generator.py b/stylized_tree_generator.py index 8b81ffe..096b44a 100644 --- a/stylized_tree_generator.py +++ b/stylized_tree_generator.py @@ -1,7 +1,7 @@ bl_info = { "name": "Stylized Tree Generator", "author": "D4rkst3r", - "version": (1, 2, 0), + "version": (1, 3, 0), "blender": (4, 2, 0), "location": "View3D > Sidebar > Tree Gen", "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.inputs[0].default_value = 1.0 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 # zu spaeten/steilen Profil (f^8) trifft die Rundung nur 1-2 Resample- # 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.inputs[1].default_value = 0.5 L(s.outputs[0], rt.inputs[0]) - # Radius NIE auf 0 laufen lassen: sonst entsteht immer eine Spitze, - # egal wie fein resampled wird. Mit Mindestradius + Fill Caps endet - # der Arm stumpf/gerundet statt als Dorn. - mx = N("ShaderNodeMath"); mx.location = (x + 450, y); mx.operation = 'MAXIMUM' - L(rt.outputs[0], mx.inputs[0]) - L(V["Tip Blunt"], mx.inputs[1]) - return mx + return rt + + # Verjuengung UND Kuppel GEMEINSAM begrenzen, dann erst mit dem Basisradius + # multiplizieren. Wirkt der Mindestwert nur auf die Kuppel, bleibt der bereits + # verjuengte Radius trotzdem winzig — gemessen: Sub-Ast-Spitze 0.8 mm bei + # 31 mm Basis, also weiterhin eine Nadel. + 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) - trad = N("ShaderNodeMath"); trad.location = (-100, 60); trad.operation = 'MULTIPLY' - L(trad0.outputs[0], trad.inputs[0]); L(tdome.outputs[0], trad.inputs[1]) + trad = _shape(inv.outputs[0], tdome, V["Trunk Radius"], -260, 60) setrad = N("GeometryNodeSetCurveRadius"); setrad.location = (-80, 200) L(_out(setpos, "Geometry"), _sock(setrad, "Curve")) @@ -275,16 +278,12 @@ def build_group(): binv = N("ShaderNodeMath"); binv.location = (440, -140) binv.operation = 'SUBTRACT'; binv.inputs[0].default_value = 1.0 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 # sein wie der Stamm (0.7+), beim Baum deutlich duenner (~0.3). - bscl0 = N("ShaderNodeMath"); bscl0.location = (760, -140); bscl0.operation = 'MULTIPLY' - L(bmul.outputs[0], bscl0.inputs[0]) - L(V["Branch Thickness"], bscl0.inputs[1]) + bbase = N("ShaderNodeMath"); bbase.location = (600, -140); bbase.operation = 'MULTIPLY' + L(V["Trunk Radius"], bbase.inputs[0]); L(V["Branch Thickness"], bbase.inputs[1]) bdome = _dome(bspar, 600, -600) - bscl = N("ShaderNodeMath"); bscl.location = (1080, -140); bscl.operation = 'MULTIPLY' - L(bscl0.outputs[0], bscl.inputs[0]); L(bdome.outputs[0], bscl.inputs[1]) + bscl = _shape(binv.outputs[0], bdome, bbase.outputs[0], 780, -140) bsetr = N("GeometryNodeSetCurveRadius"); bsetr.location = (600, 40) L(_out(bres, "Curve"), _sock(bsetr, "Curve")) @@ -415,14 +414,11 @@ def build_group(): sinv = N("ShaderNodeMath"); sinv.location = (2400, 900) sinv.operation = 'SUBTRACT'; sinv.inputs[0].default_value = 1.0 L(stap.outputs[0], sinv.inputs[1]) - srad = N("ShaderNodeMath"); srad.location = (2550, 900); srad.operation = 'MULTIPLY' - L(V["Trunk Radius"], srad.inputs[0]); L(sinv.outputs[0], srad.inputs[1]) - srad1 = N("ShaderNodeMath"); srad1.location = (2700, 900); srad1.operation = 'MULTIPLY' - srad1.inputs[1].default_value = 0.24 # duenner als Hauptaeste - L(srad.outputs[0], srad1.inputs[0]) + 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 sdome = _dome(sspar, 2550, 1200) - srad2 = N("ShaderNodeMath"); srad2.location = (3050, 900); srad2.operation = 'MULTIPLY' - L(srad1.outputs[0], srad2.inputs[0]); L(sdome.outputs[0], srad2.inputs[1]) + srad2 = _shape(sinv.outputs[0], sdome, sbase.outputs[0], 2750, 900) ssetr = N("GeometryNodeSetCurveRadius"); ssetr.location = (2550, 760) L(_out(sres, "Curve"), _sock(ssetr, "Curve")) L(srad2.outputs[0], _sock(ssetr, "Radius"))