diff --git a/README.md b/README.md index e5ae74c..6c1faa3 100644 --- a/README.md +++ b/README.md @@ -702,6 +702,31 @@ Gegenprobe ohne die Boden-Klemmung: vier Fehler. Drei bestehende Tests zaehlten die Huelle als Render-Mesh mit und schlugen zu Recht an - sie filtern jetzt `UCX_`. +### Der Hochstamm muss auf JEDER Stufe stehen + +Bis 1.46 war am Obstbaum nur S4 kalibriert. Im Welt-Test ist der User auf einen +S3 gestossen, der sich als duenne Astgabel mit Laubklumpen las statt als +Obstbaeumchen. Gemessen ueber die Stufen lag der Kronenansatz bei +**10 / 16 / 22 / 29 %** - den freien Stamm gab es nur ganz am Ende. + +Ursache ist der allgemeine Setzlings-Faktor 0.35 auf `Branch Start`. Der bildet +die Selbstbeschneidung eines WILDEN Baums ab: junge Baeume tragen ihre Aeste +tiefer und asten sich erst spaeter auf. Beim Obstbaum stimmt das nicht - ein +**Hochstamm wird gezogen, nicht gewachsen**: die Baumschule veredelt hoch und +nimmt die unteren Triebe weg, der freie Stamm ist von Anfang an da. Genau daran +haengt der Hochstamm-Charakter, und genau den verlor der Baum in den +Zwischenstufen. + +`GROWTH_OVERRIDES["obstbaum"] = {"Branch Start": 1.0}` - jetzt 29 % auf allen +vier Stufen. `tests/test_obstbaum.py` prueft das ueber die ganze Wachstumsreihe; +Gegenprobe ohne die Ausnahme: drei Fehler. + +Nebenbei ein Definitions-Hinweis, der beim Vergleich mit der Spielseite wichtig +war: dort wird "Ansatz" ueber den tiefsten BLATT-Vertex gemessen, hier ueber den +tiefsten AST-Vertex. Die Spielseite sah deshalb einen Einbruch in der Mitte +(33/17/13/21 %), wir eine monotone Reihe - dasselbe Preset, zwei Definitionen. +Der Befund stimmte trotzdem: die Zwischenstufen hatten keinen freien Stamm. + ### Blattwerk als Halbkugel-Bueschel, und groessere Baeume Drei Aenderungen, die zusammengehoeren. diff --git a/blender_manifest_tree.toml b/blender_manifest_tree.toml index 0a57db4..18f3d39 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.46.1" +version = "1.47.0" name = "Stylized Tree Generator" tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen" maintainer = "D4rkst3r" diff --git a/dist/index.html b/dist/index.html index a53300b..0d376c6 100644 --- a/dist/index.html +++ b/dist/index.html @@ -50,17 +50,17 @@ 34.5KB - stylized_tree_generator-1.46.1 + stylized_tree_generator-1.47.0 Stylized Tree Generator Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen link 4.2.0 - ~ all all - 53.0KB + 53.3KB -

Built 2026-08-07, 10:40

+

Built 2026-08-07, 11:33

diff --git a/dist/index.json b/dist/index.json index e78b892..e65cf41 100644 --- a/dist/index.json +++ b/dist/index.json @@ -82,7 +82,7 @@ "id": "stylized_tree_generator", "name": "Stylized Tree Generator", "tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen", - "version": "1.46.1", + "version": "1.47.0", "type": "add-on", "maintainer": "D4rkst3r", "license": [ @@ -98,9 +98,9 @@ "Mesh", "Modeling" ], - "archive_url": "./stylized_tree_generator-1.46.1.zip", - "archive_size": 54254, - "archive_hash": "sha256:5860c1f85899dea531bcb44e88060fe61f44906aabf924dd37b8109f81fd364a" + "archive_url": "./stylized_tree_generator-1.47.0.zip", + "archive_size": 54533, + "archive_hash": "sha256:0c1ba47d4fe89d1c45dbff090d04feaa136bea349cd30386127bc70ab2acd8eb" } ] } \ No newline at end of file diff --git a/dist/stylized_tree_generator-1.46.1.zip b/dist/stylized_tree_generator-1.46.1.zip deleted file mode 100644 index d4808ce..0000000 Binary files a/dist/stylized_tree_generator-1.46.1.zip and /dev/null differ diff --git a/dist/stylized_tree_generator-1.47.0.zip b/dist/stylized_tree_generator-1.47.0.zip new file mode 100644 index 0000000..caa2fd0 Binary files /dev/null and b/dist/stylized_tree_generator-1.47.0.zip differ diff --git a/stylized_tree_generator.py b/stylized_tree_generator.py index da02ec8..2d4525c 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, 46, 1), + "version": (1, 47, 0), "blender": (4, 2, 0), "location": "View3D > Sidebar > Tree Gen", "description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen", @@ -1267,6 +1267,17 @@ GROWTH_OVERRIDES = { # ihre Zweige GEMESSEN 0.27 m unter den Stammfuss; das Asset haette in UE # ueber dem Boden geschwebt. "weide": {"Branch Droop": 0.0, "Attraction Up": 0.0}, + # Ein HOCHSTAMM wird gezogen, nicht gewachsen. Der allgemeine + # Setzlings-Faktor 0.35 auf "Branch Start" bildet die Selbstbeschneidung + # eines WILDEN Baums ab - junge Baeume tragen ihre Aeste tiefer und asten + # sich erst spaeter auf. Beim Obstbaum stimmt das nicht: die Baumschule + # veredelt hoch und nimmt die unteren Triebe weg, der freie Stamm ist von + # Anfang an da. Genau daran haengt der Hochstamm-Charakter. + # + # Gemessen ohne diese Ausnahme (Kronenansatz je Stufe): 10 / 16 / 22 / 29 %. + # Nur S4 war kalibriert; im Spiel las sich ein S3 als duenne Astgabel mit + # Laubklumpen statt als Obstbaeumchen - gemeldet aus dem Welt-Test. + "obstbaum": {"Branch Start": 1.0}, "palme": {"Trunk Radius": 0.85, "Branch Length": 0.28}, # Saeulenkakteen bilden ihre Arme erst spaet: "branches normally begin to # appear when a saguaro reaches 50 to 70 years of age" - da ist er schon diff --git a/tests/test_obstbaum.py b/tests/test_obstbaum.py index 74d2da1..69c90f6 100644 --- a/tests/test_obstbaum.py +++ b/tests/test_obstbaum.py @@ -372,6 +372,63 @@ for seed in SEEDS: # Die Form sichert ohnehin das BREITENPROFIL schaerfer ab, als B/H es je # konnte: B/H haette sowohl den Trichter (oben/mitte 1.07) als auch die # Pilzform (unten/mitte 1.17) durchgelassen. +# --- Der HOCHSTAMM muss auf JEDER Wachstums-Stufe stehen ----------------- +# +# Bis 1.46 war nur S4 kalibriert. Im Spiel ist der User auf einen S3 gestossen, +# der sich als duenne Astgabel mit Laubklumpen las statt als Obstbaeumchen - +# gemeldet aus dem Welt-Test. Gemessen lag der Kronenansatz bei 10 / 16 / 22 / +# 29 % ueber die Stufen: den freien Stamm gab es nur ganz am Ende. +# +# Ursache war der allgemeine Setzlings-Faktor auf "Branch Start", der die +# Selbstbeschneidung eines WILDEN Baums abbildet. Ein Hochstamm wird aber +# gezogen: die Baumschule veredelt hoch und nimmt die unteren Triebe weg, der +# freie Stamm ist von Anfang an da. Deshalb GROWTH_OVERRIDES. +print("") +print("%-6s %7s %7s %7s" % ("Stufe", "Hoehe", "Cards", "Ansatz")) +for o in list(bpy.context.scene.objects): + if o is not card: + bpy.data.objects.remove(o, do_unlink=True) +s.preset = "obstbaum" +s.art_name = "Stufen" +s.variant = 1 +s.seed = 1 +s.use_growth = True +s.stages = 4 +bpy.ops.object.treegen_create() +_st = sorted((o for o in bpy.context.scene.objects + if o.type == 'MESH' and o is not card + and not o.name.endswith(("_Leaf", "_Frucht"))), key=lambda o: o.name) +for o in bpy.context.scene.objects: + o.select_set(o in _st) +bpy.context.view_layer.objects.active = _st[0] +bpy.ops.object.treegen_leaves() +for _k, _x in enumerate(_st, 1): + _dg = bpy.context.evaluated_depsgraph_get() + _ev = _x.evaluated_get(_dg) + _m = _ev.to_mesh() + _vs = [v.co.copy() for v in _m.vertices] + _a = _m.attributes.get("ast_id") + _aid = [_a.data[i].value for i in range(len(_vs))] if _a else [0] * len(_vs) + _ev.to_mesh_clear() + _z0 = min(v.z for v in _vs) + _h = max(v.z for v in _vs) - _z0 + _astz = [v.z for v, i in zip(_vs, _aid) if i > 0] + _an = 100.0 * (min(_astz) - _z0) / _h if _astz else 0.0 + _bl = bpy.data.objects.get(_x.name + "_Leaf") + _n = 0 + if _bl is not None: + _ev = _bl.evaluated_get(_dg) + _m2 = _ev.to_mesh() + _n = len(_m2.polygons) // 2 + _ev.to_mesh_clear() + print("%-6s %7.2f %7d %6.0f%%" % ("S%d" % _k, _h, _n, _an)) + if not (23.0 <= _an <= 35.0): + fails.append("S%d: Kronenansatz %.0f %% - der Hochstamm muss auf JEDER " + "Stufe stehen, nicht nur bei S4 (Vorgabe ~29 %%)" + % (_k, _an)) + if _n == 0: + fails.append("S%d: keine Cards" % _k) + print("") print("Kronenradius/Card ueber alle Seeds: %.2f - %.2f" % (min(verh), max(verh))) print("Krone unten/mitte ueber alle Seeds: %.2f - %.2f (Pilz 0.75-0.90, "