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:
@@ -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,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"
|
||||
|
||||
Vendored
+3
-3
@@ -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>
|
||||
|
||||
Vendored
+4
-4
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user