From bb576292faa9bfefba76267c8b12e4e505f40ddd Mon Sep 17 00:00:00 2001 From: D4rkst3r Date: Wed, 29 Jul 2026 10:41:08 +0200 Subject: [PATCH] Tree Generator v1.2.0: world-space UVs, UV1-Lightmap, keine Nadelspitzen - UVMap aus Geometry Nodes (V = Bogenlaenge, U = Umfang*Radius) -> Rinde ueberall gleich dicht, Regler 'UV Scale' - 'UV1 Lightmap-UV' beim Modifier-Apply (Parity zum Rock-Generator; aktiver Kanal wird gesetzt, damit lightmap_pack UV0 nicht ueberschreibt) - Sub-Aeste enden nicht mehr als Nadeln - Test prueft jetzt beide UV-Kanaele + world-space-Skalierung Co-Authored-By: Claude Opus 4.8 --- blender_manifest_tree.toml | 2 +- dist/index.json | 8 +- dist/stylized_tree_generator-1.1.0.zip | Bin 9492 -> 0 bytes dist/stylized_tree_generator-1.2.0.zip | Bin 0 -> 10862 bytes stylized_tree_generator.py | 115 ++++++++++++++++++++++--- 5 files changed, 110 insertions(+), 15 deletions(-) delete mode 100644 dist/stylized_tree_generator-1.1.0.zip create mode 100644 dist/stylized_tree_generator-1.2.0.zip diff --git a/blender_manifest_tree.toml b/blender_manifest_tree.toml index 1d0df9f..9b7a147 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.1.0" +version = "1.2.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 6171214..bbb73f9 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.1.0", + "version": "1.2.0", "type": "add-on", "maintainer": "D4rkst3r", "license": [ @@ -48,9 +48,9 @@ "Mesh", "Modeling" ], - "archive_url": "./stylized_tree_generator-1.1.0.zip", - "archive_size": 9492, - "archive_hash": "sha256:e563fd7c056b20c3d20c779713b5891baf7843f5158e4276629b8886f1efbd9f" + "archive_url": "./stylized_tree_generator-1.2.0.zip", + "archive_size": 10862, + "archive_hash": "sha256:8297d75cf7b8d73189471b480f65e98861ee73840f0ab387fb9f2141fa80a083" } ] } \ No newline at end of file diff --git a/dist/stylized_tree_generator-1.1.0.zip b/dist/stylized_tree_generator-1.1.0.zip deleted file mode 100644 index f6eda9de0110c2405fb3b056165d3e6c7d7af6c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9492 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 diff --git a/dist/stylized_tree_generator-1.2.0.zip b/dist/stylized_tree_generator-1.2.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..1947b972955da6d677dd98fba4d42e11f04511de GIT binary patch literal 10862 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 N% Sidebar > Tree Gen", "description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen", @@ -39,12 +39,13 @@ DEFAULTS = { "Branch Bend": 0.45, # Variation je Ast (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": 1.0, # 1 = laeuft spitz zu, 0.2 = bleibt dick (Kaktus) + "Branch Taper": 0.85, # wie der Stamm: laeuft NICHT auf 0 -> keine Nadeln "Sub Count": 3, # Sub-Aeste je Hauptast (0 = aus) "Sub Length": 0.55, "Sub Up": 1.4, "Sides": 6, - "Tip Blunt": 0.0, # 0 = laeuft spitz aus (Baum), 0.45 = stumpfes Ende (Kaktus) + "UV Scale": 1.0, # Rinden-Dichte; UVs sind world-space (m) + "Tip Blunt": 0.18, # >0 verhindert Nadelspitzen (0 = spitz, 0.45 = Kaktus) "Ribs": 0.0, # senkrechte Kanneluren (0 = glatt); Kaktus ~9 "Rib Depth": 0.0, } @@ -148,6 +149,7 @@ def build_group(): add_in("Sub Up", 'NodeSocketFloat', DEFAULTS["Sub Up"], -3.0, 3.0) 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("Ribs", 'NodeSocketFloat', DEFAULTS["Ribs"], 0.0, 20.0) add_in("Rib Depth", 'NodeSocketFloat', DEFAULTS["Rib Depth"], 0.0, 0.5) @@ -405,15 +407,22 @@ def build_group(): _sock(sres, "Count").default_value = 6 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) + stap = N("ShaderNodeMath"); stap.location = (2330, 1000); stap.operation = 'MULTIPLY' + L(V["Branch Taper"], 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(sspar.outputs["Factor"], sinv.inputs[1]) + 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]) - srad2 = N("ShaderNodeMath"); srad2.location = (2700, 900); srad2.operation = 'MULTIPLY' - srad2.inputs[1].default_value = 0.14 # deutlich duenner als Hauptaeste - L(srad.outputs[0], srad2.inputs[0]) + 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]) + 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]) ssetr = N("GeometryNodeSetCurveRadius"); ssetr.location = (2550, 760) L(_out(sres, "Curve"), _sock(ssetr, "Curve")) L(srad2.outputs[0], _sock(ssetr, "Radius")) @@ -478,9 +487,34 @@ def build_group(): L(_out(circ, "Curve"), _sock(pset, "Geometry")) L(poff.outputs[0], _sock(pset, "Offset")) + # ---------- UVs (Curve to Mesh erzeugt KEINE - gemessen!) ---------- + # V = echte Bogenlaenge entlang Stamm/Ast, U = Bogenlaenge um das Profil mal + # Radius => world-space UVs: Rinde sitzt auf dickem Stamm und duennem Zweig + # gleich dicht. Attribute VOR Curve to Mesh ablegen, danach kombinieren. + cspar = N("GeometryNodeSplineParameter"); cspar.location = (2250, 60) + stv = N("GeometryNodeStoreNamedAttribute"); stv.location = (2400, 200) + stv.domain = 'POINT'; stv.data_type = 'FLOAT' + L(_out(join, "Geometry"), _sock(stv, "Geometry")) + _sock(stv, "Name").default_value = "uv_v" + L(cspar.outputs["Length"], _sock(stv, "Value")) + + crad = N("GeometryNodeInputRadius"); crad.location = (2250, -80) + stw = N("GeometryNodeStoreNamedAttribute"); stw.location = (2550, 200) + stw.domain = 'POINT'; stw.data_type = 'FLOAT' + L(_out(stv, "Geometry"), _sock(stw, "Geometry")) + _sock(stw, "Name").default_value = "uv_r" + L(crad.outputs[0], _sock(stw, "Value")) + + pspar2 = N("GeometryNodeSplineParameter"); pspar2.location = (2250, -700) + stu = N("GeometryNodeStoreNamedAttribute"); stu.location = (2400, -100) + stu.domain = 'POINT'; stu.data_type = 'FLOAT' + L(_out(pset, "Geometry"), _sock(stu, "Geometry")) + _sock(stu, "Name").default_value = "uv_u" + L(pspar2.outputs["Length"], _sock(stu, "Value")) + c2m = N("GeometryNodeCurveToMesh"); c2m.location = (1500, 200) - L(_out(join, "Geometry"), _sock(c2m, "Curve")) - L(_out(pset, "Geometry"), _sock(c2m, "Profile Curve")) + L(_out(stw, "Geometry"), _sock(c2m, "Curve")) + L(_out(stu, "Geometry"), _sock(c2m, "Profile Curve")) # Falle 7 (Blender 5.x!): "Curve to Mesh" wertet das Radius-Attribut NICHT # mehr implizit aus, sondern hat einen eigenen "Scale"-Eingang. Ohne diese # Verbindung bleibt der Stamm immer bei Profil-Radius 1.0 (= 2 m dick), @@ -493,8 +527,31 @@ def build_group(): except KeyError: pass + # UVMap aus den drei Attributen zusammensetzen (FACE_CORNER, sonst kein UV) + na_u = N("GeometryNodeInputNamedAttribute"); na_u.location = (2700, -300) + na_u.data_type = 'FLOAT'; _sock(na_u, "Name").default_value = "uv_u" + na_v = N("GeometryNodeInputNamedAttribute"); na_v.location = (2700, -420) + na_v.data_type = 'FLOAT'; _sock(na_v, "Name").default_value = "uv_v" + na_r = N("GeometryNodeInputNamedAttribute"); na_r.location = (2700, -540) + na_r.data_type = 'FLOAT'; _sock(na_r, "Name").default_value = "uv_r" + + umul = N("ShaderNodeMath"); umul.location = (2880, -300); umul.operation = 'MULTIPLY' + L(_out(na_u, "Attribute"), umul.inputs[0]); L(_out(na_r, "Attribute"), umul.inputs[1]) + us = N("ShaderNodeMath"); us.location = (3030, -300); us.operation = 'MULTIPLY' + L(umul.outputs[0], us.inputs[0]); L(V["UV Scale"], us.inputs[1]) + vs = N("ShaderNodeMath"); vs.location = (3030, -420); vs.operation = 'MULTIPLY' + L(_out(na_v, "Attribute"), vs.inputs[0]); L(V["UV Scale"], vs.inputs[1]) + uvvec = N("ShaderNodeCombineXYZ"); uvvec.location = (3180, -360) + L(us.outputs[0], uvvec.inputs["X"]); L(vs.outputs[0], uvvec.inputs["Y"]) + + stuv = N("GeometryNodeStoreNamedAttribute"); stuv.location = (1650, 60) + stuv.domain = 'CORNER'; stuv.data_type = 'FLOAT2' + L(_out(c2m, "Mesh", "Geometry"), _sock(stuv, "Geometry")) + _sock(stuv, "Name").default_value = "UVMap" + L(uvvec.outputs[0], _sock(stuv, "Value")) + shade = N("GeometryNodeSetShadeSmooth"); shade.location = (1650, 200) - L(_out(c2m, "Mesh", "Geometry"), _sock(shade, "Geometry")) + L(_out(stuv, "Geometry"), _sock(shade, "Geometry")) L(_out(shade, "Geometry"), gout.inputs[0]) return ng @@ -593,12 +650,43 @@ class TreeGenSettings(PropertyGroup): name="Modifier anwenden", default=False, description="Ergebnis als normales Mesh einfrieren (fuer den Export)", ) + generate_lightmap_uv: BoolProperty( + name="UV1 Lightmap-UV", default=True, + description=("Zweiter, nicht ueberlappender UV-Kanal fuer Unreal-Lightmaps. " + "Braucht 'Modifier anwenden' (nur echte Meshes lassen sich unwrappen)"), + ) def _place(ob, x): ob.location.x = x +def _add_lightmap_uv(context, ob, op): + """UV1 fuer Unreal-Lightmaps. Nur auf echten Meshes moeglich (nach Apply).""" + if not ob.data.polygons: + return + lm = ob.data.uv_layers.get("Lightmap") or ob.data.uv_layers.new(name="Lightmap") + # WICHTIG: aktiven Kanal setzen, sonst ueberschreibt lightmap_pack UV0. + ob.data.uv_layers.active = lm + for o in context.view_layer.objects: + try: + o.select_set(False) + except (ReferenceError, RuntimeError): + pass + ob.select_set(True) + context.view_layer.objects.active = ob + try: + bpy.ops.uv.lightmap_pack(PREF_CONTEXT='ALL_FACES', PREF_PACK_IN_ONE=True, + PREF_NEW_UVLAYER=False, PREF_BOX_DIV=12, + PREF_MARGIN_DIV=0.2) + except RuntimeError as exc: + op.report({'WARNING'}, "Lightmap-UV: %s" % exc) + # UV0 wieder als Kanal 0 / Render-UV (Unreal nutzt die Reihenfolge) + if ob.data.uv_layers: + ob.data.uv_layers.active_index = 0 + ob.data.uv_layers[0].active_render = True + + class TREEGEN_OT_create(Operator): bl_idname = "object.treegen_create" bl_label = "Baum erzeugen" @@ -643,6 +731,10 @@ class TREEGEN_OT_create(Operator): bpy.ops.object.modifier_apply(modifier="GN_Tree") except RuntimeError as exc: self.report({'WARNING'}, "Modifier-Apply: %s" % exc) + continue + # UV0 heisst nach dem Apply "UVMap" (aus den Geometry Nodes). + if s.generate_lightmap_uv: + _add_lightmap_uv(context, ob, self) context.view_layer.update() total = 0 @@ -683,6 +775,9 @@ class VIEW3D_PT_tree_generator(Panel): box = layout.box() box.label(text="Export") box.prop(s, "apply_modifier") + row = box.row() + row.enabled = s.apply_modifier + row.prop(s, "generate_lightmap_uv") layout.separator() layout.operator("object.treegen_create", icon='OUTLINER_OB_MESH')