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
+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