Tree Gen 1.44.0: _Pieces_All.fbx steht auf der Stammbasis

Die Zusammenbau-Datei trug den SZENEN-Nullpunkt mit: ein Baum bei x = 18 m
exportierte gemessen mit X 16.5..19.3, Y -8.7..-6.2. Die Einzel-Teile hatten
das Problem nie (sie sitzen auf ihrem Massenmittelpunkt), der Stand-Baum folgt
der Stammbasis seit 1.36 - nur diese eine Datei fiel heraus.

Der Versatz kommt aus DERSELBEN Funktion wie beim Stand-Baum: die Rechnung ist
aus _origin_bottom_center als _stammbasis_versatz herausgeloest und wird von
beiden Wegen benutzt. Zwei Rechnungen fuer denselben Nullpunkt waeren genau die
Fehlerklasse, die hier schon dreimal zugeschlagen hat - und hier haette sie
besonders weh getan, weil die zusammengesetzten Truemmer exakt auf dem Platz
des Baums liegen muessen.

Angewendet nur fuer diesen Export, danach zurueckgenommen: mit "Teile behalten"
staenden sie sonst verschoben neben dem Baum in der Szene.

test_faell_teile stellt den Baum jetzt bewusst auf (18, -7.5) und prueft den
Stammfuss ueber den QUERSCHNITT auf Fusshoehe, nicht ueber die Bbox-Mitte - die
Krone haengt einseitig und wuerde den Fehler verwischen.
Gegenprobe ohne Versatz: Stammfuss bei 18.000 / -7.500, exakt der gemeldete
Wert.

27 Tests bestehen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 06:59:04 +02:00
co-authored by Claude Opus 4.8
parent 20e8e24322
commit b5ec4a4bc0
8 changed files with 98 additions and 13 deletions
+24
View File
@@ -563,6 +563,30 @@ Der Kaktus erzeugt regulaer **0 Cards** — kein Ast ist duenner als `Max Radius
und das ist botanisch richtig. Vorher lief das still durch und man stand vor
einer leeren `_Leaf`-Ebene; jetzt sagt der Operator es und nennt den Regler.
### Die Gesamtdatei steht jetzt auch auf der Stammbasis
`_Pieces_All.fbx` trug den SZENEN-Nullpunkt mit: ein Baum bei x = 18 m
exportierte gemessen mit X 16.5..19.3, Y -8.7..-6.2. Die Einzel-Teile hatten
das Problem nie - sie sitzen ohnehin auf ihrem Massenmittelpunkt -, und der
Stand-Baum folgt der Stammbasis-Konvention seit 1.36. Nur die
Zusammenbau-Datei fiel heraus.
Der Versatz kommt aus **derselben Funktion** wie beim Stand-Baum
(`_stammbasis_versatz`, aus `_origin_bottom_center` herausgeloest). Zwei
Rechnungen fuer denselben Nullpunkt waeren genau die Fehlerklasse, die hier
schon dreimal zugeschlagen hat - und hier haette sie besonders weh getan: die
zusammengesetzten Truemmer muessen exakt auf dem Platz liegen, wo der Baum
stand.
Angewendet wird der Versatz nur fuer diesen Export und danach zurueckgenommen.
Mit "Teile behalten" staenden sie sonst verschoben neben dem Baum in der Szene.
Geprueft wird ueber den STAMMQUERSCHNITT auf Fusshoehe, nicht ueber die
Bbox-Mitte: die Krone haengt einseitig, eine Bbox-Mitte wuerde den Fehler
verwischen. Der Test stellt den Baum dafuer bewusst auf (18, -7.5) - bei
(0,0,0) faellt so etwas nicht auf. Gegenprobe ohne den Versatz: Stammfuss bei
18.000 / -7.500, genau der gemeldete Wert.
### UCX auch in der Gesamtdatei - und zwei Fehler, die dabei auffielen
`_Pieces_All.fbx` kam ohne Kollision an, waehrend die Einzeldateien welche
+1 -1
View File
@@ -1,7 +1,7 @@
schema_version = "1.0.0"
id = "stylized_tree_generator"
version = "1.43.0"
version = "1.44.0"
name = "Stylized Tree Generator"
tagline = "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen"
maintainer = "D4rkst3r"
+3 -3
View File
@@ -50,17 +50,17 @@
<td>34.1KB</td>
</tr>
<tr>
<td><tt><a href="./stylized_tree_generator-1.43.0.zip?repository=.%2Findex.json&blender_version_min=4.2.0">stylized_tree_generator-1.43.0</a></tt></td>
<td><tt><a href="./stylized_tree_generator-1.44.0.zip?repository=.%2Findex.json&blender_version_min=4.2.0">stylized_tree_generator-1.44.0</a></tt></td>
<td>Stylized Tree Generator</td>
<td>Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen</td>
<td><a href="https://git.d4rkst3r.de/D4rkst3r/stylized-rock-generator">link</a></td>
<td>4.2.0 - ~</td>
<td>all</td>
<td>all</td>
<td>49.0KB</td>
<td>49.5KB</td>
</tr>
</table>
<center><p>Built 2026-08-07, 04:53</p></center>
<center><p>Built 2026-08-07, 04:59</p></center>
</body>
</html>
+4 -4
View File
@@ -82,7 +82,7 @@
"id": "stylized_tree_generator",
"name": "Stylized Tree Generator",
"tagline": "Parametrische Baeume, Palmen, Bueschen mit Wachstums-Stufen",
"version": "1.43.0",
"version": "1.44.0",
"type": "add-on",
"maintainer": "D4rkst3r",
"license": [
@@ -98,9 +98,9 @@
"Mesh",
"Modeling"
],
"archive_url": "./stylized_tree_generator-1.43.0.zip",
"archive_size": 50130,
"archive_hash": "sha256:2d87c780f90befc057e6895762c151bd6f4e9514485f5eb98b64993f6304893f"
"archive_url": "./stylized_tree_generator-1.44.0.zip",
"archive_size": 50734,
"archive_hash": "sha256:e10cf2efafc751b2e8b7cf6e15a793408f43ffff8b1dc0e98e43ad8ba809659a"
}
]
}
Binary file not shown.
Binary file not shown.
+39 -5
View File
@@ -1,7 +1,7 @@
bl_info = {
"name": "Stylized Tree Generator",
"author": "D4rkst3r",
"version": (1, 43, 0),
"version": (1, 44, 0),
"blender": (4, 2, 0),
"location": "View3D > Sidebar > Tree Gen",
"description": "Parametrischer Baum-/Palmen-/Busch-Generator (Geometry Nodes) mit Wachstums-Stufen",
@@ -2804,8 +2804,22 @@ def _origin_bottom_center(ob):
# Baum ohnehin fuer die Faell-Teile traegt. Ein Schwellwert auf den
# Achsabstand waere die naheliegende Alternative und faellt beim Kaktus um:
# dessen Stamm ist dicker als jeder sinnvolle Schwellwert.
stamm_verts = _stamm_koordinaten(me)
versatz = _stammbasis_versatz(_stamm_koordinaten(me))
me.transform(versatz)
return versatz
def _stammbasis_versatz(stamm_verts):
"""Versatz, der die STAMMBASIS auf den Ursprung legt.
Eine Stelle fuer beide Wege: der Stand-Baum-Export und die Gesamtdatei der
Faell-Teile muessen denselben Nullpunkt benutzen, sonst passen die
zusammengesetzten Truemmer nicht auf den Platz des Baums. Zwei Rechnungen
fuer dieselbe Frage waeren genau die Fehlerklasse, die hier schon dreimal
zugeschlagen hat.
"""
if not stamm_verts:
return Matrix.Identity(4)
zs = [c.z for c in stamm_verts]
z_fuss = min(zs)
# X/Y aus dem UNTERSTEN RING, nicht aus der Bbox des ganzen Stammes: ein
@@ -2823,9 +2837,7 @@ def _origin_bottom_center(ob):
mx = (min(xs) + max(xs)) * 0.5
my = (min(ys) + max(ys)) * 0.5
versatz = Matrix.Translation((-mx, -my, -z_fuss))
me.transform(versatz)
return versatz
return Matrix.Translation((-mx, -my, -z_fuss))
@@ -3126,6 +3138,21 @@ class TREEGEN_OT_export_pieces(Operator):
# Sie entstehen HIER und nicht in der Schleife weiter unten: dort
# sitzt jedes Teil schon auf seinem eigenen Massenmittelpunkt, in
# der Gesamtdatei stehen alle noch an ihrer Originalposition.
# URSPRUNG auf die STAMMBASIS, wie beim Stand-Baum seit 1.36.
# Vorher trug die Datei den Szenen-Nullpunkt mit: ein Baum bei
# x = 18 m exportierte gemessen mit X 16.5..19.3, und die Spielseite
# musste beim Import nachzentrieren. Die EINZEL-Teile hatten das
# Problem nie - sie sitzen ohnehin auf ihrem Massenmittelpunkt.
#
# Der Versatz kommt aus DERSELBEN Funktion wie beim Stand-Baum, denn
# die zusammengesetzten Truemmer muessen genau auf dem Platz liegen,
# wo der Baum stand.
basis_versatz = _stammbasis_versatz(
[stamm_src.matrix_world @ c
for c in _stamm_koordinaten(stamm_src.data)])
for t in teile:
t.data.transform(basis_versatz)
hullen = []
if s.piece_ucx:
for t in teile:
@@ -3151,6 +3178,13 @@ class TREEGEN_OT_export_pieces(Operator):
bpy.data.objects.remove(h, do_unlink=True)
if hm.users == 0:
bpy.data.meshes.remove(hm)
# Versatz zurueck. Fuer die Einzeldateien ist er egal - die setzen
# ihren Pivot ohnehin auf den Massenmittelpunkt -, aber mit "Teile
# behalten" staenden sie sonst verschoben neben dem Baum in der
# Szene.
zurueck = basis_versatz.inverted()
for t in teile:
t.data.transform(zurueck)
# --- Je Teil eine Datei, Pivot = Massenmittelpunkt --------------
geschrieben = 0
+27
View File
@@ -58,12 +58,19 @@ bpy.ops.object.treegen_create()
baum = [o for o in bpy.context.scene.objects
if o.type == 'MESH' and o.name.startswith("Eiche_01")
and not o.name.endswith(("_Leaf", "_Frucht"))][0]
# Der Baum steht BEWUSST nicht am Ursprung. Die Gesamtdatei trug den
# Szenen-Nullpunkt mit (gemessen X 16.5..19.3 bei einem Baum auf x = 18), und
# bei (0,0,0) faellt genau das nicht auf.
STANDORT = (18.0, -7.5, 0.0)
baum.location = STANDORT
for o in bpy.context.scene.objects:
o.select_set(o is baum)
bpy.context.view_layer.objects.active = baum
s.leaf_card = card
bpy.ops.object.treegen_leaves()
blatt = bpy.data.objects.get(baum.name + "_Leaf")
if blatt is not None:
blatt.location = STANDORT
# Referenz: wie viele Blatt-Faces hat der Stand-Baum?
dg = bpy.context.evaluated_depsgraph_get()
@@ -236,6 +243,26 @@ if gesamt:
fails.append("Gesamtdatei nur %.2f m hoch - die Teile stehen nicht an "
"ihrer Originalposition" % hoehe)
# URSPRUNG auf der Stammbasis, wie beim Stand-Baum. Geprueft ueber den
# STAMMQUERSCHNITT, nicht ueber die Bbox-Mitte: die Krone haengt einseitig,
# und eine Bbox-Mitte wuerde den Fehler verwischen. Gesucht wird auf
# Fusshoehe ein Ring von Vertices, der die Achse umschliesst.
stamm_teile = [o for o in teile if "_Piece_Stamm" in o.name]
if stamm_teile:
sco = [o.matrix_world @ v.co for o in stamm_teile
for v in o.data.vertices]
zmin = min(c.z for c in sco)
band = [c for c in sco if c.z <= zmin + hoehe * 0.03]
mx = sum(c.x for c in band) / len(band)
my = sum(c.y for c in band) / len(band)
print("Gesamtdatei: Stammfuss bei %.3f / %.3f / %.3f" % (mx, my, zmin))
if math.hypot(mx, my) > hoehe * 0.02:
fails.append("Gesamtdatei: Stammfuss liegt bei %.2f/%.2f statt "
"ueber dem Ursprung - die Datei traegt den "
"Szenen-Nullpunkt mit" % (mx, my))
if abs(zmin) > hoehe * 0.02:
fails.append("Gesamtdatei: Stammfuss bei Z %.3f statt 0" % zmin)
print("")
if fails:
print("ERGEBNIS: %d FEHLER" % len(fails))