Nur Doku und Test-Kommentare, keine Geometrie-Aenderung - deshalb kein
Versionssprung.
Die Spielseite hat den Dauerkonflikt aufgeloest: Kronenradius >= 1.80 schlaegt
B/H <= 0.75. Zweimal war die Abwaegung dieselbe (Kronenradius traegt die
Frucht-Streuung), beim zweiten Mal wurde daraus eine Regel statt einer
Einzelfallentscheidung. Die gemessenen 0.77-0.82 sind der Preis der
Frucht-Tragflaeche.
Sachlich richtig ist das auch deshalb, weil B/H die Form gar nicht absichert:
es haette sowohl den Trichter (oben/mitte 1.07) als auch die Pilzform
(unten/mitte 1.17) durchgelassen. Das Breitenprofil trennt beide sauber.
Festgehalten in test_obstbaum.py (Kopf + Kommentarblock), im Preset selbst und
in der README - damit die Abwaegung nicht ein drittes Mal von vorn gefuehrt
wird. Im Preset stehen jetzt die Neun-Seed-Werte statt der alten
Drei-Seed-Zahlen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Baum erfuellte Kronenradius, Deckung, Kronenansatz und Tri-Budget - und sah
trotzdem falsch aus. Sichtbar wurde es erst am BREITENPROFIL der Krone in
Dritteln (unten/mitte/oben, Messung der Spielseite nachgestellt):
Eiche 3.0 / 2.8 / 2.6 oben/mitte 0.90 (liest sich als Baum)
Obstbaum 3.3 / 4.5 / 4.7 oben/mitte 1.07 (Trichter)
Kein einzelner Regler hat das geloest: Crown Taper (-0.10 bis +0.50), Branch
Droop (0.6-1.2), Crown Bulge (1.0-1.8) und Attraction Up einzeln durchgefahren
liessen oben/mitte bei rund 1.0 stehen. Der Grund ist strukturell: die
Kronenform folgt nicht der Astlaenge je Hoehe, sondern dem WEG DER ASTSPITZEN.
Solange die Aeste aufwaerts schwingen, landet das aeusserste Laub oben.
Loesung ist eine andere Bauform, kein Feintuning - kurze Aeste an einem hohen
Stamm statt langer Aeste an einem kurzen:
Height 3.8 -> 4.9, Branch Length 2.55 -> 1.25, Branch Start 0.52 -> 0.40,
Attraction Up +0.40 -> -0.05, Crown Taper -0.30 -> +0.15,
Crown Bulge 0.60 -> 1.10, Branch Droop 0.35 -> 0.40.
Ueber alle neun Produktions-Seeds: oben/mitte 0.63-0.84, Kronenradius
1.88-2.01 m, Deckung 100-134 % der Eiche, 3752-4166 Tris, Ansatz 39 %.
Beim Einregeln kippte die Form zwischendurch in eine PILZform (unten am
breitesten) - deshalb steht das Profil jetzt als Test da. test_obstbaum prueft
oben/mitte <= 0.85. Gegenprobe mit den 1.39er Werten: neun Fehler bei 0.98-1.11.
B/H liegt jetzt bei 0.77-0.82 (Band der Spielseite 0.55-0.75). Bleibt bewusst
ungeprueft, wie beim Kronenradius entschieden: die Vorgaben Kronenradius >= 1.80
und B/H <= 0.75 sind bei 4-5 m Hoehe nur im Mittel gleichzeitig erfuellbar.
26 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Obstbaum las sich in der Engine als einzelne belaubte Ast-Schlaeuche mit
Himmel dazwischen. Die Card-Zahl erklaert das nicht; die Blattflaeche pro
Kronenvolumen tut es:
Eiche (schliesst) 444 Cards, Krone 18.9 m3 -> 24.6 m2/m3
Obstbaum vorher 399 Cards, Krone 36.2 m3 -> 11.4 m2/m3
Fast doppeltes Volumen bei gleicher Card-Zahl.
Der Vorschlag der Spielseite - mehr und laengere Sub-Aeste als Fuellwerk -
wurde durchgemessen und VERWORFEN: Sub Count 5/7, Sub Length 1.0/1.3, Sub Start
0.20/0.30, Branch Count 12/14 bewegten den Fuellgrad um hoechstens 7 Punkte und
trieben die Dreiecke auf 4310-5162. Strukturell: neue Zweige wachsen aus
denselben wenigen Hauptaesten und vergroessern dabei die Krone, das Volumen
waechst also mit.
Ebenfalls verworfen: mehr Cards (Ziel 740 = 5426 Tris, 26 % ueber Budget, und
der Fuellgrad stieg nur auf 75 %). Und eine kleinere Krone: Branch Length 2.35
sah ueber drei Seeds mit 1.83 m gut aus, im Neun-Seed-Test fielen SECHS Seeds
unter die 1.80 m der Frucht-Streuung.
Was wirkt, ist die Card-GROESSE (neu: LEAF_SIZE_PRESET, Faktor je Preset). Sie
kostet kein Dreieck, weil die Card-Zahl gedeckelt ist - aber OVERDRAW, und der
ist bei Bueschel-Cards der eigentliche Engpass. Deshalb der maessige Faktor
1.47: Deckung von 46 auf 87-114 % der Eiche, Card-Flaeche 414 -> 893 m2, bei
3697 statt 3714 Tris. Faktor 1.71 brachte 79 % Fuellgrad bei 2.7-facher
Flaeche - das waere eine Overdraw-Entscheidung der Spielseite.
test_obstbaum prueft die Deckung jetzt mit, und zwar gegen die im SELBEN Lauf
gemessene Eiche statt gegen eine feste Zahl: die Deckung haengt an der
Card-Flaeche, eine 6-Tri-Card bringt das Dreifache einer flachen Raute. Der
erste Anlauf des Checks ist genau daran gescheitert.
Gegenprobe gefahren: mit Faktor 1.0 meldet der Test 9 Fehler bei 42-54 % der
Eiche.
26 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Zwei-Pfade-Fehler behoben (von der Spielseite gemeldet)
Blattwerk entstand an zwei Stellen - Haekchen "_Leaf anlegen" beim Erzeugen
und Knopf "Blattwerk streuen" - und nur der zweite rechnete die
Wachstums-Staffel. Am Modifier nachgemessen trug der S1-Setzling aus dem
Create-Pfad Size 0.85, Max Radius 0.04, Min Height 0.25: die Altbaum-Werte.
Zum dritten Mal dieselbe Fehlerklasse (nach Stufen-Deckung und build_group):
zwei Quellen fuer dieselbe Frage. Die Staffel liegt jetzt in make_leaves
selbst und zieht growth_t/preset vom Baum-Objekt - ein Aufrufer KANN sie
nicht mehr vergessen. Darueber blattwerk_streuen() als der eine Einstieg
fuer beide Knoepfe, inklusive der Dichte-Regelung, die vorher ebenfalls nur
der Operator hatte. Nebenbei bekommt der Create-Pfad damit auch die
Card-SAMMLUNG, die ihm bisher fehlte.
test_zwei_pfade.py prueft die DIFFERENZ zwischen beiden Wegen, nicht die
absoluten Werte - ein Test, der nur einen Weg anschaut, findet so etwas nie.
Plus die Gegenprobe im Test selbst: waeren beide Wege gleich falsch, muss
auffallen, dass S1 und S4 dieselbe Card-Groesse tragen.
Gegenprobe gefahren: mit dem alten Create-Pfad meldet der Test 10 Fehler und
reproduziert exakt die gemeldeten 0.85 / 0.04 / 0.25.
2) Generischer "baum" entsaeult
Gemessen B/H 0.18 ueber fuenf Seeds - schmaler als jedes andere Laubgehoelz.
Ursache dieselbe wie bei der Birke: Branch Up 1.3 aus den DEFAULTS. Zielband
der Spielseite 0.45-0.60, jetzt 0.55 (0.52-0.56).
Die DEFAULTS bleiben unangetastet - sie sind die Socket-Vorgaben, an denen
die haendischen Regler haengen. Nur "baum" bekommt eigene Werte.
26 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Neues Preset "obstbaum" (Apfel/Kirsche/Birne)
Eigenes Preset statt Umbau von "baum": der wird anderswo verwendet, und ein
Hochstamm ist keine Standard-Silhouette.
Der Zweck ist funktional, nicht bloss optisch: die Frucht-Streuung setzt
Fruechte auf die AUSSENHAUT der Krone. Am generischen baum war der
Kronenradius 0.78 m bei 1.28 m Card-Diagonale - die Cards waren groesser als
die Krone, es gab keine Haut.
Proportion belegt (Hochstamm): Kronenansatz 180-220 cm, Krone selbst 3-4 m.
Ergibt 4.8 m Gesamthoehe und knapp 40 % Ansatz - genau das Band der
Spielseite.
Gemessen ueber alle NEUN Seeds der Spielseite: Hoehe 4.91-5.12 m,
Kronenradius 1.83-2.05 m, Ansatz 38-40 %, Kronenradius/Card 2.15-2.42,
3560-3824 Tris. Deckelung auf 420 Cards ueber LEAF_STUFEN_PRESET, sonst
4304-4400 Tris.
Zwei Fallen, gemessen statt vermutet: "Height" ist die STAMMlaenge, nicht die
Baumhoehe (Height 4.8 ergab 5.4-6.2 m), und der Kronenansatz zaehlt gegen die
GESAMThoehe (Branch Start 0.37 ergab 29 %).
test_obstbaum.py prueft die funktionale Bedingung ueber alle neun Seeds. B/H
ist BEWUSST nicht hart geprueft: B/H 0.55-0.75 und Kronenradius >= 1.80 bei
4-5 m Hoehe lassen zusammen nur ein 4 % breites Fenster, waehrend die Streuung
von Seed zu Seed 12 % betraegt. Vorrang hat der Kronenradius.
2) Card-Groesse misst sich an der BAUMHOEHE
Mit 0.45/0.63/0.82/1.00 schrumpfte die Card um Faktor 2.2, der Baum um 6.2.
Gemessen an der Birke 27/14/11/9 % der Baumhoehe, an der Eiche 33 gegen 11 -
der Setzling trug relativ dreimal so grosses Laub wie der Altbaum.
Jetzt 0.24/0.46/0.75/1.00: 14/10/10/9 %. Nicht ganz flach, ein junger Baum
traegt seine Bueschel relativ groeber; auf Altbaum-Proportion gezwungen
(0.18) wird er kahl.
test_blatt_bueschel prueft die Spreizung jetzt direkt und ueber Inseln statt
ueber Face-Index-Paare.
HINWEIS an die Spielseite: der Addon-Pfad skaliert S1 auf 0.45 der
S4-Groesse, auf BEIDEN Wegen nachgemessen (Einzelcard und Sammlung). Die
dort gemessenen 0.76 entstehen also erst danach - bitte growth_t am
S1-Objekt direkt vor treegen_leaves pruefen, das muss 0.0 sein.
25 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) Ursprung: Stammbasis statt tiefstem Slot-0-Punkt
Zweimal war das schon "behoben". Erst kam der Ursprung aus der Gesamt-Bbox
(eine Blatt-Card hob den Baum an), dann aus Material-Slot 0 - aber die AESTE
gehoeren ebenfalls zum Rinden-Slot. Gemessen an Tanne_01_S1: tiefster
Slot-0-Punkt -5.35 cm, tiefster STAMM-Punkt -0.02 cm. Die Stammbasis
schwebte 5.3 cm ueber dem Boden.
Die exakte Trennung liefert ast_id (0 = Stamm) - dasselbe Attribut, das der
Baum fuer die Faell-Teile ohnehin traegt. Ein Schwellwert auf den
Achsabstand faellt beim Kaktus um: dessen Stamm ist dicker als jeder
sinnvolle Schwellwert. X/Y kommt jetzt aus dem untersten RING statt aus der
Stamm-Bbox; bei Bend 1.5 liegt die Bbox-Mitte in der Kruemmung.
Neu: tests/test_ursprung.py, gemessen am reimportierten FBX. Die erste
Fassung des Tests suchte den "tiefsten Punkt nahe der Achse" - die
Gegenprobe hat sie umgeworfen, weil bei der Tanne eine Astspitze ins
Achsband faellt. Ein Schwellwert, der die Bugfassung durchlaesst, prueft
nichts. Jetzt wird ein Stammquerschnitt gesucht: Vertices, die die Achse in
allen Himmelsrichtungen umschliessen. Gegenprobe bestanden.
Nebenbefund: ein Baum ohne Aeste traegt gar kein ast_id (Branch Count 0
schaltet den Ast-Zweig des Graphen ab). Dann ist alles Stamm und der
Fallback exakt.
2) Weide S4 auf 350 Cards gedeckelt - Entscheidung des Users
Gemessen 5456-5594 Tris ueber drei Seeds gegen 4300 Budget; nach der
Deckelung 3890-3962. LEAF_STUFEN_PRESET haelt solche Ausnahmen je Preset.
3) Birke war eine Saeule
Gemessen B/H 0.15 - schmaler als der Standardbaum (0.22), nicht die Haelfte
der Eiche (0.36). Ursache: Branch Up 1.1, die Aeste klebten am Stamm.
Zielband 0.35-0.55 aus Van den Berk (8-12 m bei 15-20 m) und Woodland Trust
(6-10 m bei 15-25 m); jetzt 0.51.
Haengende Zweigenden ueber Branch Droop 0.8 + Droop Curve 3.5, nicht ueber
negatives Sub Up: das wurde von +2.2 bis -2.0 durchgemessen und bewegt
nichts (1-6 %), weil die Sub-Aeste zu kurz sind. Mit Droop 26 % bei einem
Fall von 0.033 x Hoehe - wie die Tanne (0.030), weit weg von der Weide
(0.213).
4) run_tests.ps1 benennt Blender-Abstuerze
test_export_robust starb rund in jedem sechsten Lauf mit
EXCEPTION_ACCESS_VIOLATION und der Runner meldete "<keine Ergebniszeile>".
Der Stack enthaelt keinen einzigen Addon-Frame (RNA_property_int_get ->
rna_property_rna_or_id_get -> IDP_GetPropertyFromGroup, Null-Deref), und mit
eingebauten Markern verschwindet der Absturz: Heisenbug in Blender 5.1.2.
Der Runner wiederholt jetzt einmal und benennt den Absturz.
24 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) build_group riss Szenen-Baeume ab
Die Gruppe GN_Tree wurde bei JEDEM Erzeugen geloescht und neu angelegt -
damit zeigten alle bereits erzeugten Baeume auf ein totes Datablock und
evaluierten leer. Gemessen: nach vier Arten-Erzeugungen lebte nur noch die
letzte. Dass direkt nach dem Erzeugen exportiert wurde, hat das verdeckt.
Jetzt ein Waechter mit ZWEI Kriterien: abgelegte Schema-Version
(TREE_SCHEMA) UND die tatsaechlich vorhandenen Eingaenge. Die Version allein
reicht nicht - wer waehrend der Entwicklung Sockets aendert ohne die Zahl
anzufassen, bekaeme eine veraltete Gruppe untergeschoben. Muss doch neu
gebaut werden, werden bestehende Modifier auf die neue Gruppe umgehaengt.
Beide Pfade gemessen: vier Arten nacheinander leben alle (624/796/924/1036
Verts), und nach build_group(rebuild=True) ebenfalls unveraendert.
2) Saemlinge zu duenn
Die McMahon-Skalierung macht duennstaemmige Arten am Setzling zu Draehten:
Birke 0.6 cm Fussradius gegen 1.9 der Eiche - dreimal duenner, waehrend der
Unterschied beim Altbaum nur 1.2x betraegt. Die Regel gilt fuer die Statik
ausgewachsener Baeume; ein Saemling ist eine Pflanze, kein Balken.
SEEDLING_MIN_RADIUS + SEEDLING_MIN_FLARE heben die duennen Arten an, ohne
die dicken anzufassen. Danach liegen alle bei 2.8 cm.
test_proportionen laesst die McMahon-Abweichung genau dort zu, wo der Boden
greift, und prueft dass sie nicht weiter geht - die Regel bleibt sonst scharf.
23 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zwei Befunde von der Spielseite.
1) Dichte-Kompensation ueberschoss preset-abhaengig
Die Eichung am Standardbaum (11 Cards / 486 Tris) kam auf der Eiche als
1008 Tris an. Ursache ist strukturell: "Dichte" ist Punkte pro m2
Zweigflaeche, und die verteilt sich je Preset voellig anders. Jeder
Konstanten-Satz haette fuer den naechsten Baum neu geeicht werden muessen.
Strukturwechsel wie vorgeschlagen: in LEAF_STUFEN steht jetzt die
ZIEL-STUECKZAHL (S1 10, S2 40, S3 120, S4 = volle Dichte), und der Generator
regelt die Dichte per Bisektion dagegen ein. Der Seed wird dabei nicht
angefasst - gleicher Baum und Seed ergeben dieselbe Verteilung.
Gemessen ueber vier Presets (Ziel 10 / 40 / 120):
baum 9 41 104 eiche 10 43 138
birke 9 36 136 tanne 9 38 125
Die Eiche liegt bei S1 jetzt bei 576 Tris statt 1008.
Der Test prueft die Anzahl DIREKT, statt ueber Dichte x Anteil x Flaeche zu
rechnen - genau der Punkt des Vorschlags.
2) Baum stand "etwas in der Luft"
Der Export-Ursprung kam aus der Gesamt-Bbox inklusive Blatt-Cards. Eine
einzige tief haengende Card hebt damit den ganzen Baum an. Jetzt kommt er aus
der STAMM-Geometrie (Slot 0). Gemessen an der Eiche: Stamm-min.Z 0.000 auf
allen vier Stufen, waehrend die Gesamtbox bei S1 auf -0.106 liegt - das waren
die 10 cm, um die er zu hoch stand.
Beim Einbauen selbst verursacht und behoben: eine abgebrochene Befehlskette
liess die Operator-Verdrahtung aus, wodurch die Dichte mit der ZIEL-ANZAHL
multipliziert wurde (170 x 40) - 732 Cards statt 40. Faellt sofort auf, wenn man
die Zahlen anschaut, statt den Durchlauf fuer erfolgreich zu halten.
23 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Befund aus der Turnhalle: die Setzlings-Blaetter verteilen sich ueber die ganze
Stammhoehe, es entsteht eine belaubte Saeule statt einer Krone. Nachgemessen:
44 % der Cards sassen unter 40 % der Baumhoehe, die tiefste bei 6 %.
Der Radius-Filter kann das nicht loesen - er trennt duenn von dick, aber ein
junger Stamm ist UEBERALL duenn. Also ein zweiter Filter ueber die Hoehe: Laub
erst ab dem Kronenansatz, als Anteil der Baumhoehe. Die Schwelle kommt aus der
Bounding Box des Baums, nicht als Meterwert - fest waere sie beim Setzling die
halbe Pflanze und beim Altbaum wirkungslos.
Kronenansatz je Stufe (LEAF_STUFEN): S1 40 %, S2 35 %, S3 30 %, S4 25 %.
unter Ansatz tiefste Card
vorher nachher vorher nachher
S1 44 % 0 % 6 % 46 %
S2 32 % 0 % 24 % 36 %
S3 9 % 0 % 31 % 34 %
S4 3 % 0 % 34 % 34 % (unveraendert)
Beim Altbaum ist der Filter praktisch ein Sicherheitsnetz - dort sitzt ohnehin
nichts tief, genau wie gemeldet.
Dichte von S1/S2 nachgezogen: der Filter nimmt dem Setzling sonst die Haelfte
der Cards (9 -> 4), weil dessen Laub vorher ueber die ganze Stammhoehe verteilt
war. Jetzt 11 Cards bei S1, und 486 Tris gegen 800 Budget.
23 Tests bestehen (Suite zweimal durchlaufen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drei Befunde aus der Turnhalle abgearbeitet.
1) Deckung PRO STUFE statt globaler Formel
Die alte Rechnung (Dichte durch faktor^2) hielt den Setzling vor der
Kahlheit, gab ihm aber die Deckung eines Altbaums. Jetzt Tabelle
LEAF_STUFEN. S4 traegt die volle Dichte 170, S2 liegt 15 % darunter, S1
deutlich. Der Dichte-Anteil bei S1/S2 sieht hoch aus - "Dichte" ist Punkte
pro m2 ZWEIGFLAECHE, und die waechst ueber die Stufen dramatisch. Was zaehlt
ist die Anzahl: 17 / 43 / 67 / 130 Cards, Kante 0.19 / 0.29 / 0.37 / 0.45.
Budget S3/S4 auf 4300 (die Spielseite hebt ASSETS.md nach dem 170er-Export
entsprechend an).
2) Radius-Filter skaliert mit dem Wachstum (der S3-Befund)
Der Filter trennt duenne Zweige von dickem Geaest - aber mit starren 0.04 m
greift er bei jungen Baeumen nicht: gemessen sassen bei S2 81 % der Cards am
Stamm, bei S3 58 %. Jetzt 48 bzw. 52 %.
Dabei eine eigene Fehldeutung korrigiert: bei S1 bleiben ~88 % am Stamm, und
das ist KEIN Defekt. Nachgemessen ist die zulaessige Flaeche dort fuer jeden
Schwellwert identisch (0.013 m2) - der Saemling hat kein dickes Geaest, an
dem sich etwas trennen liesse. Blaetter am Stiel sind bei einem Saemling der
Normalfall. Ein erster Sweep hatte mich in die Irre gefuehrt, weil ich
growth_t=0 auf einen AUSGEWACHSENEN Baum gesetzt hatte - der hat die volle
Zweigflaeche und verhaelt sich voellig anders als ein echter Setzling.
3) LOD-Reduktion als TEILSET der LOD0-Cards
Bisher wurde je Stufe neu gestreut - die Cards sassen an anderen Stellen und
die Silhouette sprang beim LOD-Wechsel um. Jetzt wird ausgeduennt: jede
verbleibende Card liegt genau dort, wo sie in LOD0 schon war, die
Ueberlebenden werden groesser. Gearbeitet wird auf zusammenhaengenden
INSELN, nicht auf Faces - eine Card muss ganz bleiben oder ganz verschwinden.
Auswahl ist seed-stabil.
Gemessen am reimportierten FBX: 260 / 156 / 78 / 32 Blatt-Faces, und 100 %
der Cards auf LOD1-3 sitzen auf einer LOD0-Position. Der Versatz zu LOD0 ist
dabei kleiner geworden als beim Neustreuen.
23 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fehler: _origin_bottom_center backt zuerst die Weltmatrix ins Mesh und wendet
DANN die Zentrierung an - zurueck gibt es aber nur die Zentrierung. Den Stufen
1-3 wurde nur diese aufgedrueckt, ihre Weltmatrix blieb ungebacken. Ergebnis:
sie landeten bei MINUS der Standposition. Gemeldet fuer einen Baum bei x = 18 m,
dessen LOD1-3 bei x = -1894 cm sassen - exakt die Standposition, in Zentimetern
wegen FBX_SCALE_ALL. Jetzt backt jede Stufe erst ihre EIGENE Weltmatrix, dann
kommt die gemeinsame Zentrierung aus LOD0.
Warum der Test das nicht gefunden hat: er baute den Baum am URSPRUNG. Dort ist
minus null eben null. Der Baum steht jetzt bewusst bei (18, -7.5), und je Stufe
wird die X/Y-Mitte im reimportierten FBX gemessen - an derselben Stelle wie die
Radialitaets-Pruefung.
Gegenprobe gemacht: mit zurueckgedrehtem Fix meldet der Test LOD1-3 bei
-17.87/7.46, also exakt minus der Standposition, und faellt mit 6 Fehlern durch.
Mit Fix liegen alle Stufen bei 0.000-0.135 um den Ursprung.
Ausserdem Dichte 170 -> 150. Grund: mit der REALEN Diamond-Card (6 Tris, nicht
die 2-Tri-Attrappe aus meinen Sweeps) landet die Eiche bei Dichte 170 auf 4206
Tris - 2778 Krone plus 1428 Stamm - und damit ueber dem 4000er-Budget aus
ASSETS.md Teil 6. Die abgenommene Krone (2778) und das dokumentierte Budget
(4000) sind also nicht gleichzeitig haltbar. 150 liegt im abgesegneten
Sweetspot 130-170 und haelt das Budget mit 3816. Wenn der Look bei 170 wichtiger
ist, muesste das Budget auf ~4300 - das ist eine Entscheidung der Spielseite.
Nebenbei: test_leaves hatte leaf_size fest auf 0.22 stehen (alter
Blaettchen-Wert) und pruefte gegen ein fest verdrahtetes 2500er-Budget. Beides
kommt jetzt aus den Einstellungen.
23 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Blatt-Defaults auf die Bueschel-Atlas-Aera umgestellt. Eine Card ist ein ganzer
Zweigbueschel, kein einzelnes Blatt - die alten Werte streuten hunderte winziger
Cards, wo ein paar Dutzend grosse hingehoeren. Werte an einer S4-Eiche in UE
gemessen und abgenommen:
Groesse 0.22 -> 0.85
Dichte 500 -> 170
Max Radius 0.02 -> 0.04 <- der Volumen-Hebel
Kippung 0.5 -> 0.9
Max Radius ist der unscheinbare Held: bei 0.02 trugen nur die aeussersten
Zweigspitzen Laub, die Krone hatte nur Kontur und war innen nackt.
Bueschelgroesse haengt jetzt am Wachstum: make_object merkt growth_t am Objekt
(aus dem Namen zu lesen waere bruechig), der Blattwerk-Operator skaliert die
Cards damit. Gemessen ueber vier Stufen: Card-Kante 0.19/0.28/0.37/0.45.
Falle dabei: "Dichte" ist Punkte pro m2 Zweigflaeche, und ein Setzling hat davon
fast keine - bei Stufe 1 kamen exakt NULL Cards heraus, der Setzling stand kahl
da. Da die Bueschel um denselben Faktor kleiner sind, deckt jeder nur faktor^2
der Flaeche; die Dichte gegenlaeufig anzuheben haelt die Blattdeckung gleich.
Tri-Budget PRO STUFE (ASSETS.md Teil 6): S1 <= 800, S2 <= 1200, S3/S4 <= 4000.
Bewusst Stufen und keine Interpolation; die Schwellen greifen auch bei drei
Stufen richtig (t = 0 / 0.5 / 1.0). Gemessen 494 / 878 / 1032 / 1396 - alle im
Rahmen.
WICHTIGSTE FALLE, von der UE-Seite gemeldet und hier nachgestellt:
md[socket] = wert loest KEINE Neuauswertung des GN-Modifiers aus. Die
Blattebene blieb bei 118 Faces stehen, obwohl die Dichte von 90 auf 400
geschrieben war - auch view_layer.update() half nicht, erst ein
show_viewport-Toggle. Der Knopf-Weg funktionierte bisher nur ZUFAELLIG, weil
make_leaves jedes Mal auch die Objekt-Zeiger neu schreibt und das Aendern eines
ID-Zeigers die Depsgraph-Beziehungen umbaut. Wer das spaeter optimiert ("nur
geaenderte Werte schreiben"), haette den Fehler still zurueck.
_modifier_anstossen() macht es jetzt explizit - in make_leaves UND make_object.
Nebenbei: der Variantentest rundete Card-Flaechen auf 5 Stellen; seit die
Kippung bei 0.9 steht streuen sie in der sechsten und eine einzige Card-Sorte
zerfiel in vier Eimer.
Neu: tests/test_blatt_bueschel.py. 23 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Punkt 5 - LOD-Kette fuer den Stand-Baum
Haken "LOD-Kette erzeugen" liefert <Name>_LODGroup.fbx mit _LOD0..3 unter
einem fbx_type=LodGroup-Empty, wie die Fels-Pipeline. NUR der Stand-Baum -
die Faell-Teile leben Sekunden als Physik-Actor, dort reicht LOD0.
Blatt-Reduktion ueber die DICHTE, nicht ueber Decimate: eine Card besteht aus
zwei Dreiecken und laesst sich nicht vereinfachen, man muss weniger davon
setzen. Die verbleibenden werden groesser, damit die Krone nicht ausduennt.
LOD0 578 Rinde / 170 Blatt / 1306 Tris
LOD1 477 / 118 / 912
LOD2 364 / 66 / 575
LOD3 221 / 28 / 302 (16 % der Cards von LOD0)
Kugel-Normalen auf JEDER Stufe gemessen, nicht nur LOD0 - LOD1-3 haben eine
eigene Card-Verteilung. Am reimportierten FBX: 100 % radial auf allen vier.
Zwei Reihenfolge-Sachen: das Rinden-Decimate laeuft VOR dem Verschmelzen,
danach wuerde es die Blatt-Cards mit einschmelzen. Und der Ursprung kommt aus
LOD0 (Unreal platziert danach); alle Stufen werden um denselben Betrag
verschoben, sonst springt der Baum beim LOD-Wechsel.
Punkt 6 - Aufraeumen und Pruefen
Blatt-Streuung ueber alle neun Presets nachgemessen. Der Max-Radius-Filter
arbeitet richtig: 0-22 % der Cards landen am Stamm (meist unter 9 %), und
alle Presets bleiben unter dem 2500-Tri-Budget (Maximum weide 2246).
Messfalle, die ich dabei selbst produziert habe: zuerst hatte ich den Anteil
der VERTICES unter der Radius-Schwelle gemessen - beim Busch 95 %, sah nach
einem Problem aus. Das misst aber die Vertex-Verteilung, nicht wo Blaetter
landen; ein Busch besteht fast nur aus duennen Zweigen. Die richtige Frage
beantwortet erst ast_id.
Der Kaktus erzeugt regulaer 0 Cards (kein Ast duenner als Max Radius, botanisch
richtig). Das lief still durch und man stand vor einer leeren _Leaf-Ebene -
jetzt sagt der Operator es und nennt den Regler beim Namen.
Panels: das Export-Panel trug Stand-Baum, LODs und Faell-Teile in einem
Kasten. Die Teile haben jetzt "5 - Faell-Teile" fuer sich.
Neu: tests/test_baum_lod.py. 22 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Knopf "Faell-Teile exportieren": Stamm in 2-3 Segmente, jeder Ast als eigenes
Teil SAMT seinen Sub-Aesten und Blatt-Cards, dazu <Name>_Pieces_All.fbx mit
gemeinsamem Ursprung. Je Teil zwei Material-Slots, Pivot am Massenmittelpunkt,
eigene UCX-Huelle.
Die Ast-Zugehoerigkeit ist ein ATTRIBUT, keine Schaetzung - wie von der
UE-Seite vorgeschlagen. Der Generator legt "ast_id" an den Astpunkten ab
(0 = Stamm, 1..N = Aeste). Sub-Aeste erben die ID ihres Astes automatisch, weil
sie aus Punkten auf dessen Kurve entstehen; nachgemessen: bei Sub Count 0 hat
jeder Ast 28 Verts, bei 3 dann 64, der Stamm bleibt konstant bei 156. Beim
Blatt-Streuen wird ast_id am Punkt abgegriffen und auf die Card gespeichert.
Damit ist die Zuordnung exakt nachzaehlbar, und genau das prueft der Test:
Summe der Cards ueber alle Teile == Cards des Stand-Baums. 170 = 170.
Die Falle, die diese Bilanz aufgedeckt hat: die Z-Schnitte am Stamm zerschnitten
anfangs auch Blatt-Cards. Aus einer wurden zwei, die Bilanz stand auf 178 gegen
170 - und die Atlas-UVs der Haelften waeren kaputt gewesen. Eine Card ist ein
unteilbares Billboard; sie wandert jetzt als GANZES in das Segment, in dem ihre
Inselmitte liegt. Nur die Rinde wird geschnitten, ihre Schlagflaechen werden
gedeckelt.
Massenmittelpunkt flaechengewichtet statt Vertex-Mittelwert: wo das Mesh dicht
tesselliert ist (Astansatz), wuerde der Mittelwert den Pivot dorthin ziehen und
das Teil torkelte beim Fallen.
Alles am REIMPORTIERTEN FBX gemessen: 12 Teile (3 Stamm, 9 Ast), UCX 18-32
Verts im Budget, Pivot maximal 16 mm vom Schwerpunkt, 0 non-manifold Kanten,
Gesamtdatei 5.41 m hoch - also volle Baumhoehe und deckungsgleich
rekonstruierbar.
Nebenbei: _deselect fiel ueber None-Eintraege in der Objektliste, die beim
Entfernen von Objekten zwischen den Teilen staendig auftreten.
Neu: tests/test_faell_teile.py. 21 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"Leaf Card" kann jetzt eine COLLECTION sein: je Blattpunkt wird zufaellig eine
Card gezogen (Pick Instance, seed-stabil). Damit legt der Nutzer 4-6
Diamond-Cards mit unterschiedlichen Atlas-UVs an und die Krone mischt sie.
Rueckwaertskompatibel - ein einzelnes Objekt geht weiter, die Sammlung hat
Vorrang.
Umsetzung: Collection Info mit Separate Children (sonst kaeme die Sammlung als
ein Klumpen an und Pick Instance haette nichts zum Auswaehlen), Geometry-Switch
zwischen Einzel- und Sammlungspfad, Instanz-Index aus einem Random Value, dessen
Obergrenze aus der TATSAECHLICHEN Anzahl kommt - eine feste Obergrenze wuerde
bei weniger Cards Luecken erzeugen. Geometry Nodes kann einen leeren
Collection-Zeiger nicht selbst pruefen, deshalb setzt make_leaves einen
"Use Collection"-Schalter.
Beweisfuehrung im Test: die Zufalls-Groesse wird ABGESCHALTET, dann kommt jede
Groessenabweichung nur von der Card-Variante und die Anzahl verschiedener
Face-Flaechen ist ein exakter Zaehler. Gemessen: Einzel-Card 2 Flaechen (ein
Card-Paar), Sammlung mit 4 Cards 10 Flaechen - alle Varianten kommen vor.
Gleicher Seed identisch, anderer Seed anders.
Nebenbei: die Vorpruefung des Blattwerk-Operators war eine zusammengesetzte
Bedingung, die bei gesetzter Sammlung ohne Einzel-Card auf None zugriff.
Neu: tests/test_blatt_varianten.py. 20 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Punkt 1 - "Spielfertig exportieren"
Stamm und _Leaf-Ebene werden zu EINEM Mesh mit zwei Material-Slots
verschmolzen (Slot 0 = M_Bark, Slot 1 = M_Foliage). Die getrennten Objekte
im Blend bleiben die Arbeitsebene - verschmolzen wird nur eine Export-Kopie.
Ursprung Bbox-Unterseite Mitte und FBX-Einstellungen wie in der
Fels-Pipeline (use_selection, FBX_SCALE_ALL).
Punkt 2 - Kugel-Normalen auf die Blatt-Cards
Alle Blatt-Normalen zeigen radial vom Kronen-Schwerpunkt nach aussen, damit
die Krone als EIN weiches Volumen liest statt als Haufen flacher Bleche.
Der Schwerpunkt wird nur aus den BLATT-Faces gebildet - der Stamm wuerde die
Mitte nach unten ziehen und die Kugel verkippen.
Bewusst direkt ueber normals_split_custom_set statt ueber den
Normal-Edit-Modifier: der Modifier muesste vor dem Export angewendet werden,
und angewendete Modifier plus Custom Normals ist genau die Kombination, bei
der der FBX-Export gerne flachbuegelt. Am REIMPORTIERTEN FBX gemessen:
mittlere Radialitaet 1.000, 100 % der 510 Blatt-Loops ueber 0.8. Gegenprobe
Rinde 0.043 - die bleibt unangetastet.
Drei Fallen unterwegs:
- Ueber bmesh.from_mesh zusammenfuegen haengt die Geometrie zwar an, wirft
aber die MATERIAL-INDIZES weg: danach lagen alle 748 Faces auf Index 0,
Blaetter und Rinde ununterscheidbar. Blenders join fuehrt die Slot-Listen
zusammen und rechnet die Indizes korrekt um.
- join loescht das zweite Objekt; jede gehaltene Referenz darauf ist danach
tot. Die Aufraeumliste fuehrt deshalb NAMEN statt Objekte.
- Die Export-Kopie muss exakt so heissen wie der Baum (Unreal leitet den
Asset-Namen davon ab). Solange das Original den Namen haelt, haengt Blender
".001" an - Original wird fuer die Exportdauer beiseite benannt, wie bei den
Felsen.
Neu: tests/test_baum_export.py misst die Normalen im EXPORTIERTEN FBX, nicht
am Szenenobjekt - nur so faellt ein plattgebuegelter Custom-Normal auf.
19 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Weniger einstellen muessen: oben im Panel Sorte waehlen, Haken druecken,
erzeugen. Die neun Unter-Panels bleiben fuer den Feinschliff.
Findling rund, weiche Kanten ~1160 V / ~2320 Tris
Platte flach, liegt satt auf ~670 V / ~1340 Tris
Kantig Bevel + Weighted Normal ~350 V / ~690 Tris
Erzbrocken dicht genug fuer die Maske ~1280 V / ~2560 Tris, Slot M_Rock_Ore
dissolve_angle ist jetzt ein BEREICH statt eines festen Werts - direkt aus der
Rueckmeldung "hab ich immer auf 17-25 je nach Stein". Je Stein wird einer
gezogen; gemessen an sechs Findlingen bei 17-25 Grad: 1936-2928 Tris. Beide
Regler gleich setzen = fester Winkel wie frueher.
Zwei Sachen fielen beim Messen auf:
1) Der Dissolve-Winkel frisst deutlich Geometrie. Derselbe dichte Satz liefert
bei niedrigem Standardwinkel ~2700 Tris, bei 17-25 Grad nur noch ~1030 und
faellt damit unter ORE_MIN_VERTS - das Erz-Set haette seine EIGENE Warnung
ausgeloest, sobald vorher eine Sorte mit hohem Winkel gewaehlt war. Der
Bereich gehoert deshalb mit in DENSE_PRESET. Ueber vier Seeds und beide
Groessenklassen nachgemessen: 0.70/0.92 haelt den Worst Case bei 847 Verts.
2) Erz-Dichte und Tri-Fenster kollidieren. Die Maske braucht ~800 Verts auch
beim kleinen S-Brocken, das treibt einen M-Stein auf ~3400 Tris - ueber das
Fenster 1500-3000. Deshalb entkoppelt: normale Sorten leichter (0.40/0.80),
Erzbrocken knapper (0.45/0.82), das S+M-SET dichter (0.70/0.92), weil dort
die kleinen Brocken die Untergrenze setzen.
Nebenbei gefunden und behoben: der erzwungene Ursprung wurde aus der
GEMEINSAMEN Bbox aller LOD-Stufen berechnet. Eine stark dezimierte Stufe kann
tiefer reichen als LOD0 - dann sass LOD0 sieben Zentimeter ueber dem Pivot und
der Stein haette in UE geschwebt. Unreal platziert nach LOD0, also gibt LOD0
jetzt den Ursprung vor.
Neu: tests/test_schnellstart.py. 18 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drei Rueckmeldungen von der Spielseite abgearbeitet.
1) Fehlende Material-Slots
"Material zuweisen" stand auf Standard AUS, deshalb kamen alle Proben mit
mats: [] an - Unreal legt dann nur einen Default-Slot an und die
eingefrorene Konvention M_Rock_<Sorte> greift nicht. Jetzt Standard AN.
Normale Steine rotieren durch M_Rock_Granite/Basalt/Sandstone/Mossy, das
Erzfels-Set bekommt einen NEUTRALEN Slot M_Rock_Ore - ein Set fuer alle
Erzsorten, die Sorte macht die Material-Instanz.
2) Namens-Drift Fels_ statt Rock_
War ein Versehen, keine Absicht: der Standard-Praefix stammte noch aus der
ersten Fassung, bevor die Konvention Rock_<Set>_<Groesse>_<NN> stand. Der
Erz-Set-Knopf setzte "Rock" schon selbst, der allgemeine Standard nicht.
Standard ist jetzt "Rock" - keine Asset-Zwillinge, keine Migration noetig.
3) Erzfelsen mit ~870 statt ~2700 Tris
Nachgestellt: aus den Werkseinstellungen liefert der Set-Knopf 2590-2690
Tris, die Automatik greift also. ~870 entstehen genau dann, wenn man den
Erz-Haken setzt und den NORMALEN Erzeugen-Knopf nimmt - Werkseinstellung ist
Decimate 0.20/0.50 statt 0.40/0.80. Das ist eine Bedienluecke, kein Fehler
in der Automatik: die Dichte wird bewusst nur ueber den Set-Knopf gesetzt,
damit niemandem seine Einstellungen unterm Hintern weggezogen werden.
Deshalb warnt der Operator jetzt, wenn mit Erz-Haken ein Mesh unter 800
Verts entsteht, und nennt den Knopf "Smooth & dicht" beim Namen. Sonst
faellt das erst in UE auf und sieht dort nach einem Material-Fehler aus.
Tests halten den Vertrag jetzt fest: Auslieferungszustand (assign_material an,
Praefix Rock), neutraler Erz-Slot, Sorten-Slots bei normalen Steinen.
17 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entscheidung der Spielseite: die A-Semantik bleibt eingefroren (1.0 = kein Erz),
der Master loest es ueber
Erz = (1 - A) * ErzMenge
mit ErzMenge als MI-Regler, Standard 0. Normale Stein-MIs ignorieren den Kanal
damit vollstaendig, nur die Erz-MIs drehen ihn auf. Kein Re-Export des
25er-Sets noetig, keine Fallunterscheidung im Addon.
Dafuer musste die Maske umgedreht werden: bisher lag das Nugget-ZENTRUM auf
A = 1.0 - also auf demselben Wert wie "kein Erz". Unter der Master-Formel waere
das Erz damit unsichtbar gewesen und der ganze RESTLICHE Stein haette als Erz
gegolten. Jetzt laufen die Nuggets auf A = 0 zu.
Gemessen: ohne Erz A 1.00..1.00 und (1-A) max 0.000 - ein normaler Stein zeigt
im Master garantiert nichts. Mit Erz erreicht (1-A) 1.00, Abdeckung unveraendert
4/9/15 % bei Anteil 0.08/0.18/0.35. Die Erzstellen sitzen an denselben Punkten
wie vorher, nur andersherum kodiert.
Die Tests pruefen jetzt direkt gegen die Master-Formel statt gegen den Rohwert -
am Rohkanal ist die Richtung zu leicht zu verwechseln. Panel zeigt bei aktivem
Erz-Bake "A=Erz (0=Erz)" plus den Hinweis auf die Formel, damit das niemand
versehentlich zurueckdreht.
Nugget-Groesse bleibt wie entschieden ABSOLUT (Radius in Metern).
ACHTUNG: Erz-Assets, die mit 2.15/2.16 exportiert wurden, tragen die alte
Richtung und muessen neu exportiert werden. Steine ohne Erz-Bake sind nicht
betroffen - deren A war und ist durchgehend 1.0.
17 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Kein Laufzeit-Fracturing im Spiel - die Teile werden beim Anschlagen als
Physik-Actors gespawnt, entstehen hier also als vollwertige Assets.
Knopf "In Bruchstuecke zerlegen" arbeitet auf der Auswahl: <Name>_Piece_01..NN,
2-4 Teile, Bruch-Seed, optional Mutterstein ausblenden. Jedes Teil bekommt
Vertex-Layout v2, Ursprung unten-mittig, die gleichen Material-Slots wie der
Mutterstein und beim Export eine eigene UCX-Huelle.
Punkt 4a: "Ein Stueck mit Erz" benennt ein zufaelliges Teil <Name>_Piece_Erz
und schreibt Erz-Adern in dessen A-Kanal. Alle anderen Teile behalten A = 1.0.
Ob es gespawnt wird, entscheidet die Loot-Logik im Spiel.
Zusammenpassende Bruchkanten ohne Abstimmung: Voronoi ueber Halbraeume. Fuer
jedes andere Zentrum wird an der Mittelsenkrechten geschnitten und die
abgewandte Seite verworfen - benachbarte Zellen schneiden dadurch an GENAU
derselben Ebene. Bewusst ohne das Cell-Fracture-Addon (muesste aktiviert sein,
haengt an Operator-Kontext); bmesh laeuft immer.
Die Falle, die mich mehrere Anlaeufe gekostet hat: jeder Schnitt muss SOFORT
geschlossen werden, und zwar ueber genau die Kanten aus geom_cut. Der
naheliegende Weg - am Ende alle Randkanten suchen und fuellen - erzeugte Kanten
mit vier Flaechen (hauchduenne Splitter, 0.000007 m2 gegen Median 0.0025);
raeumte man die ab, blieben Loecher. dissolve_degenerate half nicht, weil es
nach KantenLAENGE geht und ein langer duenner Splitter keine kurze Kante hat.
Aufgefallen ist das Ganze am Volumen, nicht am Auge: die Teile kamen zusammen
auf 72.7 % des Muttersteins, weil calc_volume bei offenen Meshes Unsinn
liefert. Jetzt 100.2 % bei 2, 3 und 4 Teilen, 0 offene und 0 non-manifold
Kanten. Genau dieser Vergleich steht im Test - er ist zugleich das Warnsignal
fuer kaputte Topologie.
Neu: tests/test_bruchstuecke.py. 17 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Punkt 5 - EIN neutrales Erzfels-Set fuer ALLE Erzsorten
A-Kanal traegt die Erz-Maske: sie sagt nur WO Erz sitzt. WELCHES Erz
(Kupfer/Eisen/Gold = Tint + Gluehen) macht die Material-Instanz in UE.
Knopf "Erzfels-Set erzeugen (S + M)" liefert Rock_Ore_S_NN und Rock_Ore_M_NN
und setzt alle Einstellungen danach zurueck. Regler: Erz-Anteil,
Nugget-Groesse (Radius in m), Erz-Seed.
Nuggets statt Noise: gestreute Zentren mit weichem Abfall. Ein Noise-Feld
gaebe wolkige Schlieren, Erz sitzt aber in abgegrenzten Einschluessen. Die
Zentren bevorzugen Fugen - Adern folgen Rissen, und das Gluehen liest sich
in einer Vertiefung besser.
Ohne Erz-Bake bleibt A auf 1.0 - wie im eingefrorenen Layout v2 und wie das
bestehende 25er-Set es traegt.
Punkt 6 vorgezogen, weil Punkt 5 davon abhaengt
Die Maskenaufloesung haengt an der Vertex-Dichte. Bei den bisherigen
~150-Vert-Steinen war jedes dritte Vertex ein Nugget-Zentrum: im Render
liefen die Nuggets zu grossen Schlieren zusammen statt einzelne Einschluesse
zu bleiben. Bei ~1350 Verts liest es sich richtig. Deshalb gibt es jetzt
"Smooth & dicht" (Unterteilung 5, Decimate 0.40/0.80, Auto-Smooth) und das
Erz-Set stellt selbst darauf um. Gemessen ueber drei Seeds: 2708/2658/2716
Tris - im Zielfenster 1500-3000. Zusaetzlich ist die Nuggetzahl auf ein
Zentrum je ~10 Verts gedeckelt.
Nebenbei: _asset_name schrieb die Form-Bezeichnung pauschal gross, daraus wurde
"Rock_ORE_S_01" statt des vereinbarten "Rock_Ore_S_01". Einzelne Buchstaben
(Form A, B, C) werden weiter gross geschrieben, laengere Bezeichner behalten
ihre Schreibweise.
Gemessen: Erz-Anteil 0.08 -> 4 %, 0.18 -> 9 %, 0.35 -> 15 % der Oberflaeche,
A 0.00..1.00, S bis 0.80 m / M ab 1.71 m, Maske ueberlebt den FBX-Roundtrip.
Neu: tests/test_erz.py. 16 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Punkt 1 - Ursprung erzwingen (keine Option mehr)
Der Export schrieb die Objekt-Transformation mit ins FBX. Dadurch trug das
25er-Set seine Szenen-Rasterpositionen (bis 20 m) im Asset und die Steine
schwebten im Spiel neben ihrem Platzierungspunkt. Jetzt wandert jedes Objekt
an den Welt-Ursprung, Origin unten-mittig der Bbox. Am REIMPORTIERTEN FBX
gemessen: Bbox-Mitte 0.000/0.000, min.Z 0.000.
Punkt 2 - flache Steine hinlegen
Kuerzeste Bbox-Achse zeigt nach oben. Gedreht wird nur, wenn es etwas bringt:
bei 2.53/1.40/1.54 wuerde Kippen die Form nur willkuerlich drehen.
Punkt 3 - UCX-Kollisionshuellen
Konvexe Huelle als UCX_<Name> im selben FBX, Budget einstellbar (Default 32
Verts). Gemessen 29-32 Verts, geschlossen, umschliesst den Stein.
Alles auf temporaeren KOPIEN - die Szene des Users bleibt unveraendert
(Test prueft Namen und Objektzahl vorher/nachher).
Offener Punkt der Spielseite beantwortet: LOD-Gruppen + Vertex-Farben gingen
NICHT. Der LOD-Zweig in make_one_rock sprang komplett am Cavity-Bake vorbei -
gemessen: kein Farbattribut auf einer der vier Stufen, dazu fehlten Origin und
Material. Jetzt wird auf LOD0 gebacken, BEVOR dupliziert wird; das Decimate
interpoliert mit, damit alle Stufen dieselbe Cavity zeigen und der LOD-Wechsel
nicht poppt. Nach Roundtrip: LOD0 40 V R 0.30..1.00, LOD1 21 V, LOD2 11 V,
LOD3 6 V - alle mit Farben.
Vier Fallen, die der Test aufgedeckt hat:
- Blender haengt an Kopien ".001" an; Unreal ordnet UCX ueber den EXAKTEN
Mesh-Namen zu -> Original bekommt fuer die Exportdauer einen Hilfsnamen.
- bmesh.from_mesh bringt die Originalflaechen mit, convex_hull legt seine
Huelle obendrauf -> 16-21 offene Kanten. Nur die PUNKTE einlesen.
- Jede Vereinfachung schneidet Ecken ab, die Huelle wird KLEINER als der Stein
(der Spieler wuerde einsinken). Jetzt exakt so weit aufgeblasen, dass wieder
alles hineinpasst - fuer Kollision ist minimal zu gross unkritisch.
- ob.matrix_world = Identity loescht die Transformation NICHT bei geparenteten
Objekten; bei einer LOD-Gruppe auf (13/-7.5/2.2) landete das Mesh bei MINUS
dieser Position. matrix_basis und matrix_parent_inverse direkt nullen.
Neu: tests/test_export_robust.py misst am reimportierten FBX statt an der
Szene - nur so faellt eine mitgeschriebene Transformation ueberhaupt auf.
15 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drei gemeldete Probleme - alle bestaetigt, Ursachen gemessen statt geraten.
1) Palme sah "extrem komisch" aus
Gemessen: Kronenradius/Hoehe 0.11 - die Wedel klebten als Mop-Kopf am
Stamm. Zielwert aus zwei unabhaengigen Quellen, die sich decken:
tree-gen palm.py (Weber&Penn) setzt Wedellaenge = 0.3 x Stamm, die
TreeIt-Referenzpalme kommt auf 3.3 m bei 4.33 m = 0.38.
Jetzt 0.30. Dazu der Winkel: tree-gen gibt down_angle 60 + curve 40 an,
also schraeg raus und ueberbiegen. Mit Branch Up 0 allein standen die
Wedel als gerade Antennenspeichen ab; mit Up 0.35 / Droop 1.2 steigen sie
gemessen 1.1 m ueber den Ansatz und kippen dann ab.
2) Busch sah aus wie ein Baum
Gemessen: 1.81 m hoch bei 0.84 m Breite (B/H 0.46), durchgehender Stamm,
Aeste erst ab 15 %, Wurzelanlauf wie beim Baum. Das IST ein Baeumchen.
Botanisch ist der Unterschied nicht die Groesse, sondern die Architektur:
mehrere Stiele ab Boden, kein Leittrieb, gemessen nach Hoehe UND Breite.
Jetzt kurzer Stumpf + Aeste ab Boden: 1.20 m hoch, 2.0 m breit (B/H 1.6).
3) Kleinste Wachstumsstufe sah komisch aus / "nur runterskaliert"
Gemessen: der Setzling war relativ zu seiner Hoehe 2.4x DICKER als der
Altbaum (r/H 0.025 gegen 0.0104), weil Trunk Radius mit 0.30 skalierte,
die Hoehe aber mit 0.16. Botanisch gilt die elastische Aehnlichkeit nach
McMahon: Hoehe ~ Durchmesser^(2/3), also Faktor 0.16^1.5 = 0.064.
Dazu behielt jeder Setzling den vollen Wurzelanlauf -> Trichterfuss.
Neu ausserdem: Aeste schrumpfen mit der Hoehe statt langsamer, sitzen
tiefer (Aufasten kommt erst mit dem Alter) und haengen weniger.
Nicht jede Pflanze waechst wie ein Laubbaum -> GROWTH_OVERRIDES:
Palme kein Dickenwachstum, erst Durchmesser dann Hoehe (UF/IFAS ENH1212:
"its diameter is fixed for life") -> Setzling ist ein kurzer Stumpf
Kaktus Sukkulent, gleiche Logik, und OHNE Arme: Saguaros bilden die erst
mit 50-70 Jahren bei rund 2 m Hoehe (NPS)
Weide haengt erst mit langen Zweigen; sonst reichten sie 0.27 m unter
den Stammfuss und das Asset waere in UE geschwebt
Zwei Bugs fielen dabei auf:
- Branch Count = 0 schaltete die Aeste NICHT ab - dieselbe Falle wie damals
bei Sub Count (Curve to Points klemmt Count auf min. 1). Fuer die Sub-Ebene
gab es laengst einen Geometry-Switch, fuer die Hauptaeste nicht.
- Im Busch-Preset stand "Branch Count" zweimal im selben Dict; der zweite
Eintrag (10) hat den ersten (14) still ueberschrieben.
Die sieben uebrigen Presets sind unveraendert (gleiche Maße, gleiche Tris).
Neu: tests/test_proportionen.py nagelt die Zielwerte fest. 14 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Panel-Umbau
-----------
Jedes Addon hatte seine Einstellungen als Kette dauerhaft offener Boxen - beim
Rock Generator 15 Stueck, man musste am ganzen Panel vorbeiscrollen, um an den
Erzeugen-Knopf zu kommen. Jetzt steht oben nur, was man bei jedem Asset anfasst
(Vorlage, Name, grosser Erzeugen-Knopf, Zufall), der Rest liegt in nummerierten,
eingeklappten Unter-Panels in der Reihenfolge des Arbeitsablaufs:
Rock Gen 9 Unter-Panels (Benennung ... Textur-Bake)
Tree Gen 4 (Wachstum, Blattwerk, Zusatz-Ebenen, Export)
Grass Gen 4 (Form, Haltung, Batch, Kanal-Belegung)
Asset Utils 5 (war schon so, dient als Vorlage)
Schalter, die ein ganzes Unter-Panel steuern (Vertex-Farben backen,
Wachstums-Stufen), sitzen jetzt als Haekchen im Panel-Kopf - Zustand sichtbar
ohne aufzuklappen.
Gemessen statt geglaubt: test_panels.py registriert alle vier Addons, laesst
jedes Panel zeichnen, prueft Tab-Zugehoerigkeit und Auf-/Zugeklappt-Absicht,
dass jeder angebotene Operator existiert - und vor allem, dass JEDE definierte
Property irgendwo erreichbar bleibt (Zweige wie base_shape='BOX' werden dabei
durchgeschaltet). Ergebnis: 0 von 122 Properties beim Umbau verloren.
Test-Suite
----------
Beim Gegenpruefen kam heraus, dass fuenf Tests still veraltet waren und eine
echte Regression nicht gemeldet haetten:
test_rock_gen suchte Objekte mit Praefix "Rock_" - die heissen seit dem
Benennungssystem "Fels_A_M_01". Fand 0 von 3.
test_base_shapes loeschte am Schleifenanfang ALLE Objekte, auch die eigenen
Kopien aus vorigen Durchlaeufen -> StructRNA removed.
test_ecogame_tree erwartete eine feste Namensliste ohne die spaeter
dazugekommenen _Leaf-Objekte.
test_tree_addon dito, ausserdem Zip-Version 1.22.0 fest verdrahtet.
test_leaves Zip-Version 1.23.0 fest verdrahtet.
Drei Muster vermieden statt nur die Symptome geflickt: neue Objekte ueber die
Differenz vorher/nachher finden statt ueber ein Namens-Praefix, Zips per glob
statt mit fester Version, Zusatz-Ebenen beim Zaehlen herausfiltern.
Neu: run_tests.ps1 faehrt die komplette Suite mit einem Befehl (-Filter fuer
einzelne). Genau das fehlte - deshalb war das Veralten nicht aufgefallen.
13 von 13 Tests bestehen.
Nebenbei
--------
build.ps1 ruft server-generate jetzt mit --html auf (browsbare index.html fuer
statisches Hosting). Nachgemessen und im README festgehalten: zwei Zips
derselben Extension-ID sind KEIN Versions-Archiv - server-generate warnt
("archive found with duplicates ... conflicting blender versions"), mehrere
Versionen einer ID gehen nur bei verschiedenen Blender-Bereichen.
Versionen: Rock 2.13.0, Tree 1.24.0, Grass 1.1.0, Asset Utils 1.1.0
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fuer handgebaute Assets, die nicht durch einen Generator laufen (Pilze,
Baumstumpf, Erzfels, Props). Panel in fuenf einklappbaren Unter-Panels statt
einer langen Liste:
1 Vorbereiten - Rotation/Scale anwenden, Ursprung unten-mittig, Normalen
2 Vertex-Farben - R=Cavity / G=Teil-oder-Moos-Maske / B=Hoehe / A=1
3 Benennung - <Basis>_<NN>, Mesh-Daten ziehen mit
4 Pruefen - Asset-Check auf alles, was in UE Aerger macht
5 Export - FBX je Mesh mit colors_type='SRGB'
Zwei Bugs beim Bauen gefunden und gefixt:
- v.link_faces gibt es nur in bmesh, nicht auf Mesh.vertices -> lose Vertices
ueber die tatsaechlich benutzten Indizes zaehlen.
- bpy.ops.paint.vertex_color_set braucht den Vertex-Paint-Modus und scheitert im
Object-Mode mit "poll() failed". Zusammen mit vertex_color_dirt im selben try
wurde dadurch der GANZE Bake stillschweigend uebersprungen (R/G/B blieben 1.0).
Initialisierung laeuft jetzt direkt ueber Python.
Verifiziert am nachgebauten Pilz: Check meldet vorher Scale/Rotation/Ursprung,
nach "Vorbereiten" Scale 1/1/1, Rot 0/0/0, min_z 0.0000 und "ok". Teil-Maske
G=1 im Hut, 0 im Stiel. Nach FBX-Roundtrip G-Werte [0.0, 1.0] erhalten.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der User baut Pilze von Hand (Hut und Stiel als getrennte Objekte, mit Strg+J
verbunden) und fragte, was er wegen Vertex-Farben beachten muss.
Zwei Ergaenzungen:
1) Button "Vertex-Cavity auf Auswahl": backt R=Cavity / G / B=Hoehe auf JEDES
markierte Mesh - nicht mehr nur auf generierte Steine. Damit lassen sich
handgebaute Assets (Pilze, Baumstumpf, Erzfels) auf dasselbe Layout bringen.
2) Option "G = Teil-Maske (Shells)": statt der Moos-Maske werden getrennte
Mesh-Teile markiert. Der oberste/breiteste Teil bekommt G=1, der Rest 0.
Bei Strg+J-verbundenen Assets ist die Trennung dadurch EXAKT statt ueber
Normalen geschaetzt - beim Pilz also Hut vs Stiel. Ein Material toent beide
unterschiedlich, ein zweiter Material-Slot entfaellt.
Einteilige Meshes bleiben bewusst unmarkiert (G=0), damit die Maske nichts
Falsches behauptet.
Am nachgebauten Pilz geprueft: 2 Shells erkannt, G im obersten Teil ausschliess-
lich 1.0, im Rest ausschliesslich 0.0, Maske binaer, Einzelteil-Mesh -> nur 0.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Beim Export von Form C (flache Platte) fiel auf: Fels_C_S war 1.45 m, waehrend
Fels_A_S nur 0.85 m misst - dieselbe Klasse, aber deutlich groesser, nur weil
eine Achse gestreckt ist. Damit waere die Groessen-Klasse formabhaengig gewesen.
Die Proportionen werden jetzt auf geometrisches Mittel 1.0 normiert. "M" bedeutet
bei jeder Form dasselbe Volumen; eine Platte ist dann flacher UND breiter, aber
nicht schwerer. Dass ihre laengste Kante groesser ausfaellt, ist geometrisch
zwangslaeufig und Absicht.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Gras-, Blumen- und Farn-Bueschel. Kern ist die WIND-UV nach Vorgabe des Users:
UV0.V = 0 an der Wurzel, 1 an der Spitze - genau die Maske, die UEs
"SimpleGrassWind" als WindWeight braucht.
Am Zielmaterial geprueft (M_Grass.uasset): es nutzt SimpleGrassWind +
WorldPositionOffset + TextureCoordinate, aber KEINE VertexColor. Die Windmaske
kommt deshalb primaer ueber die UV - die Assets laufen damit ohne
Materialaenderung.
Vertex-Farben zusaetzlich, nicht als einzige Quelle:
R = Kopie der Windmaske (Fallback)
G = Variation je HALM - Ebene unter dem Biom-Tint, den die Engine bereits ueber
PerInstanceCustomData 0/1 pro Instanz setzt; im Material multiplizieren
B = AO (unten dunkel)
Presets gras / gras_hoch / steppengras / farn / blume, Zufalls-Button,
Tri-Budget-Warnung (400 laut ASSETS.md).
Gemessen: UV.V Wurzel 0.000 -> Spitze 1.000, 112 Tris bei 14 Halmen, G hat
exakt 14 verschiedene Werte bei 14 Halmen (also wirklich pro Halm, nicht pro
Vertex), min_z = 0.0000, UV und VCol ueberleben den FBX-Roundtrip.
build.ps1 baut jetzt drei Extensions - dieselbe URL liefert alle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Auf Wunsch des Users neben Wuerfel und Ico-Sphere eine Quader-Grundform mit
frei einstellbaren Proportionen (X/Y/Z) plus Streuung je Stein. Damit entstehen
flache Platten und langgestreckte Riegel - passt besonders zum Plattenlook der
Genshin-Referenz, wo Felsen aus flachen Schichten bestehen.
Wichtiges Detail: die Proportionen werden auf die MESH-DATEN angewendet
(transform_apply), nicht auf das Objekt. Der Displace arbeitet mit globalen
Texturkoordinaten - eine Objekt-Skalierung wuerde das Rauschen mitverzerren
statt die Form zu aendern.
Gemessen bei Proportion (2.0, 1.5, 0.35): 3.43 / 2.56 / 0.79 m (Z = 23 % von X),
bei (2.2, 0.8, 0.9): 3.81 / 1.40 / 1.60 m. Der Zufalls-Button kennt die neue
Form ebenfalls. Neuer Test tests/test_base_shapes.py.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nach Wunschliste des Users. Attribut "Cavity" traegt jetzt drei UNABHAENGIGE
Masken statt einer eingebackenen Mischung:
R = Cavity pur 1 = offene Flaeche, 0 = tiefe Fuge - OHNE Hoehen-Verlauf
G = Moos/Schmutz aus Oberseiten-Anteil + Fugennaehe + Noise, mit Reglern
fuer Menge, Aufbruch und Seed
B = Hoehen-Verlauf 0 = Unterseite, 1 = oben, separat
A = 1 (Reserve)
Der Punkt: Boden-Saum und Moosfarbe entscheidet jetzt das MATERIAL pro Instanz,
nicht mehr das Mesh. In v1 steckte der Verlauf fest in R und liess sich nicht
mehr trennen.
Gemessen: R ohne Hoehenabhaengigkeit (unten 0.62 / oben 0.59 - vorher war das
der eingebackene Verlauf), B steigt 0.08 -> 0.92, G oben 0.57 vs unten 0.20,
A konstant 1.00. Moos-Seed aendert die Verteilung. Alle drei Kanaele ueberleben
den FBX-Roundtrip.
tests/test_vertex_cavity.py prueft jeden Kanal einzeln inkl. Roundtrip.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der Export verliess sich auf den Default. Damit die Vertex-Cavity zuverlaessig in
der FBX landet, jetzt colors_type='SRGB' explizit. Verifiziert ueber einen
Roundtrip: alle 8 exportierten Felsen tragen das Attribut "Cavity" nach dem
Re-Import (Bereich 0.23..1.00).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Idee kam vom User: die Steine ueber "smart materials" in UE loesen statt ueber
gebackene Texturen. Prozedurales Noise/Voronoi im Shader waere zu teuer (laeuft
pro Pixel), aber der Kern der Idee traegt - deshalb dieser Weg:
Neue Option "Cavity in Vertex-Farben": schreibt Cavity/AO plus optionalen
Hoehen-Verlauf in das Farb-Attribut "Cavity" (vertex_color_dirt + eigene
Nachbearbeitung fuer Staerke und Verlauf). Das Material braucht damit KEINE
Textur: Base Color = Farbton x VertexColor, dazu Kantenlicht und Schattentint.
Gegenueber Triplanar sitzen die dunklen Fugen dadurch auf den ECHTEN Kanten des
Meshes statt darueberzuschweben - genau das passiert in der Genshin-Referenz.
Verifiziert: Attribut wird angelegt, Wertebereich 0.250..0.947 (echter Kontrast),
und es ueberlebt den FBX-Roundtrip UNVERAENDERT (gleicher Bereich nach Import).
Regler: Cavity-Staerke, Hoehen-Verlauf, Weichzeichnen.
Neuer Test tests/test_vertex_cavity.py.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der User hat Genshin-Screenshots als Stilvorlage geschickt. Auswertung: die
Felsen dort bestehen aus WENIGEN GROSSEN, fast leeren Platten mit SCHMALEN
DUNKLEN FUGEN. Das Detail steckt in der Fuge, nicht in der Flaeche.
Meine Textur machte das Gegenteil - viele kleine Zellen mit breitem Verlauf ueber
die ganze Oberflaeche. Deshalb half weder TexScale noch die Zellgroesse: beide
haben nur am Symptom gedreht, waehrend das Muster grundsaetzlich zu dicht war.
Neue Regler:
- "Fugenbreite" (Default 0.05): Breite des Uebergangs Fuge -> Flaeche. Klein =
harte Fuge und flache Platte. War vorher fest auf 0.32 = weicher Verlauf ueber
die ganze Zelle ("Golfball").
- "Platten flach" (Default 1.0): 1 = Flaeche nahezu einfarbig, Kontrast wandert
komplett in die Fuge.
- "Zellgroesse" heisst jetzt "Plattengroesse" (Default 0.7 statt 2.5) - kleiner
= GROESSERE Platten. Der alte Name war irrefuehrend.
Grundton auf helles warmes Grau, AO-Staerke 1.0 -> 0.55 (weniger Unruhe).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1) KLASSEN-GROESSE (vom User gemeldet): S und M kamen gleich gross raus.
Ursache war eine Luecke im Design, nicht in der Bedienung: "keep_size"
normiert die Zufalls-Streuung auf konstantes Volumen - damit wurde alles,
was ueber scale_min/max eingestellt war, wieder herausgerechnet. Fuer die
Groesse der KLASSE gab es schlicht keinen Regler.
Neu: CLASS_SIZES (S=0.45, M=1.0, L=1.9, XL=3.2) plus "Groesse aus Klasse"
und eine freie "Basis-Groesse". Die Klassengroesse ist bewusst gesetzt und
von der Streuung getrennt; sie greift auch bei abgeschalteter Randomisierung.
Gemessen: S 0.85 m | M 1.9 m | L 3.5 m | XL 6.0 m, Volumen-Streuung
INNERHALB jeder Klasse bleibt bei 1.11x (nur Form).
2) BUG im Zufalls-Button (kam mit 2.5.0): jitter() schrieb einen float in die
int-Property subsurf_levels -> TypeError, der Operator brach komplett ab.
jitter() rundet jetzt fuer Int-Properties. Von tests/test_randomize.py
gefangen.
Neuer Test tests/test_rock_classes.py deckt die Klassengroessen ab.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Blatt-Card waehlen -> wird auf die duennen Zweige gestreut (Filter ueber das
Radius-Attribut des Meshes) und als <Name>_Leaf mit identischem Ursprung abgelegt.
Regler fuer Dichte, Groesse, Streuung, Kippung, Zweig-Schwelle. Der Button meldet
Stamm + Blatt = Summe und warnt bei Ueberschreitung des Tri-Budgets.
Gemessen: Eiche 1428 + Blattwerk 1032 = 2460 von 2500 Tris bei Default-Dichte 150.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Aeste kruemmen sich zur Spitze hin zur Senkrechten - als echte Rotation um den
Astansatz, nicht als Z-Versatz. Die Astlaenge bleibt dabei erhalten (gemessen:
+0.08 m Hoehe statt +0.93 m beim alten Droop-Hack). Pro Preset abgestimmt.
Idee aus UE 5.8 Procedural Vegetation / Weber-Penn.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"Sub Count = 0" schaltete die Sub-Aeste nicht ab (Curve to Points klemmt auf 1) ->
duenne "Nadeln" bei Palme und Kaktus. Jetzt echter Geometry-Switch.
Palme am TreeIt-Referenzbaum ausgemessen: kurze Wedelstiele (0.78 m statt 3.4 m),
Stamm 4.4 m mit dickem Kronenschaft. 854 statt 1784 Tris.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Palmenstamm mit nahezu konstantem Durchmesser (Taper 0.22), glatt geschwollener
Fuss ohne Wurzelbretter, 15 kraeftige Wedelstiele im Bogen statt duenner
haengender Draehte. 1784 von 2500 Tris.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rock Generator 2.5.0:
- "Zufaellig"-Button: wuerfelt Seed und Form-Parameter, "Streuung" steuert die
Abweichung von den aktuellen Werten (0 = nur neuer Seed). Optional werden auch
Basis-Form und Noise-Typ gewuerfelt. Werte werden auf ihre Grenzen geklemmt.
- Skalierung streut jetzt die FORM, nicht die Groesse: nicht-uniform ist Default,
und "Gesamtgroesse konstant halten" normiert das geometrische Mittel auf 1.
Gemessen ueber 6 Rocks: Volumen-Spanne 1.92x -> 1.11x. Wichtig, weil EcoGame
die Groesse zusaetzlich ueber ScaleMin/Max streut.
Tree Generator 1.19.0:
- "Zufaellig"-Button: neuer Seed plus Streuung auf Hoehe, Radius, Biegung,
Ast-Anzahl/-Laenge, Kronenform und Wurzelanlauf. Preset-Charakter bleibt, weil
relativ zu den aktuellen Werten gestreut wird (gemessen: Hoehe 6.65 -> 8.34 m).
- "_Leaf"- und "_Frucht"-Ebenen: leere Objekte mit IDENTISCHEM Ursprung neben dem
Baum (gemessen: Abstand 0.000000), damit die Ebenen in UE deckungsgleich sitzen.
Vier Test-Suiten liegen jetzt unter tests/ statt nur im Scratchpad.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rock Generator 2.4.0:
- Benennung Fels_<Form>_<Klasse> statt Rock_000 (Praefix/Form/Klasse im Panel,
Klasse S/M/L/XL, optionale Durchnummerierung bei Batches)
- Bake liefert jetzt <name>_albedo und <name>_normal. AO/Cavity wird per Option
MULTIPLIKATIV ins Albedo gebacken (Staerke regelbar) - separate Roughness- und
AO-Paesse sind Default aus, weil Roughness in EcoGame eine Zahl im Master-
Material ist. Gemessen: Albedo-Mittelwert 0.549 -> 0.433 mit AO, Kontrast rauf.
- UV1 Lightmap Default AUS (EcoGame beleuchtet dynamisch)
Tree Generator 1.18.0:
- Benennung <Art>_<Variante>_S<Stufe>, z.B. Birke_01_S1..S4 (statt stage0..3);
Art-Feld und Varianten-Nummer im Panel, Art leer = Preset-Name
- UV1 Lightmap Default AUS
README: Konventionen dokumentiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Basisring trifft den TreeIt-Baum jetzt fast exakt (r 0.178 vs 0.179, Unrundheit
1.61 vs 1.60). Lappen zentriert moduliert, damit die Lappentiefe nicht mehr den
mittleren Radius mit anhebt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Zweige waren 70 % so dick wie ihre Aeste (jetzt ~35 %). Eiche und Birke hatten
durch verkettete Replaces vertauschte Ast-Dicken.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Aeste waren mit 32 % des Stammradius doppelt zu dick (Referenz: 11-16 %). Das
war die Ursache der groben Astansaetze - nicht fehlende Verschweissung.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collar-Abfall von Exponent 6 auf 2.5 (bei ~7 Segmenten pro Ast war 6 nur einen
Punkt breit = Widerhaken statt Uebergang). Trunk Radius 0.13 -> 0.085.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Beide Arme laufen flach raus, knicken und steigen parallel zum Stamm, ohne ihn
zu ueberragen (Droop und Hoehe aufeinander abgestimmt). Neu 'Trunk Tip': steuert,
ob der Stamm duenn auslaeuft oder mit stumpfer Kuppe endet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Crown Taper / Crown Bulge steuern die botanische Huellkurve (kegelfoermig bis
rund) - damit sind Tanne, Eiche, Birke, Weide und toter Baum als Presets
moeglich. Alle neun Presets liegen im Tri-Budget des Projekts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stamm rund (8 Seiten), Aeste 4, Zweige 3 - wie im TreeIt-Referenzbaum. Runderer
Stamm bei gleichzeitig ~25% weniger Tris (baum 1368 -> 1032).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 'Detail' skaliert alle Resample-Counts -> zentrale Budget-Stellschraube
- Defaults treffen jetzt das Projekt-Budget (baum 1368, busch 532 Tris)
- 'Root Flare': Wurzelanlauf am Stammfuss, kostet keine Tris
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 'Branch Collar': Aeste werden an der Basis leicht breiter -> gewachsener
Uebergang zum Stamm, ohne einen einzigen zusaetzlichen Vert
- Stammspitze laeuft duenn aus statt mit flachem Deckel zu enden
- 'Merge'/'Merge Voxel' (Voxel-Remesh) optional, Default AUS: verschmilzt Aeste
organisch, kostet aber die UVs und bis zu 14x Verts (gemessen), duenne Zweige
zerfallen -> fuer Game-Assets nicht empfohlen
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Aeste/Zweige werden per Instanz-Scale an den Radius ihres Elternpunktes gekoppelt
('Input Radius' auf der Punkt-Domain von Instance on Points). Oben am duennen
Stamm sind die Aeste dadurch automatisch kuerzer und duenner statt gleich dick.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sub-Aeste hatten gar keine Biegung -> gerade Staebe. Jetzt nutzen Stamm, Aeste
und Zweige dieselbe Noise-Kruemmung (nach Realize ueber die Weltposition, damit
jeder Zweig anders faellt). Zweige ausserdem duenn + fast gleichmaessig statt
dick-kegelig (das war die eigentliche Dorn-Ursache).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mindestdicke (Tip Blunt) wirkt jetzt auf Verjuengung*Kuppel statt nur auf die
Kuppel. Duennster Querschnitt 0.8 mm -> 7.5 mm (gemessen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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 <noreply@anthropic.com>
Die Zell-Look-Aenderung am Textur-Bake (Voronoi statt fBm, Grundfarbe/Zellgroesse
regelbar) war im vorigen Commit ohne Versions-Bump mitgelaufen -> Blender haette
kein Update angeboten. Version nachgezogen, Listing enthaelt jetzt
Rock 2.3.0 + Tree 1.0.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ein Extension-Repo kann mehrere Addons ausliefern (server-generate listet jedes
Zip in dist/) -> die bereits eingetragene Blender-URL liefert jetzt Rock UND Tree,
ein 'Check for Updates' aktualisiert beide.
- stylized_tree_generator.py: Panel 'Tree Gen', Presets baum/palme/busch/kaktus,
Wachstums-Stufen (gleicher Seed = dieselbe Baum-Identitaet), Modifier-Apply
- Node-Kern 1:1 aus EcoGame tools/blender_tree_gen.py generiert (keine Abweichung)
- build.ps1 baut jetzt beide Extensions
- Headless getestet: alle 4 Presets, Stufen aufsteigend (504/744/1236/1872), Apply ok
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Bake BaseColor/Normal/Roughness/AO als PNG
- Nahtlos tileable via 4D-Torus-Projektion der UV (cos/sin u,v)
- Cycles-Bake mit Zustands-Restore, temporaere Bake-Plane + Cleanup
- docs/UE_Material_Triplanar.md: WorldAlignedTexture/Normal-Verdrahtung
- _deselect_all gegen transiente None-Refs nach Objekt-Removal gehaertet
- Live gegen Blender 5.1.2 getestet (4 Maps, Normal jetzt mit Struktur), Headless gruen
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Fix: smart_project/dissolve_limited angle_limit jetzt in Radiant (Blender 4.x/5.x)
- Fix: Lightmap-UV-Kanal vor lightmap_pack aktiv setzen (UV0 nicht mehr ueberschrieben)
- Fehlerbehandlung pro bpy.ops-Call; einzelner Rock-Fehler bricht Batch nicht ab
- Modaler Batch-Modus mit Progress-Bar (ab modal_threshold)
- Bevel + Weighted Normal Toggle
- LOD-Set als fbx_type=LodGroup-Gruppe fuer Unreal
- Preset-System (JSON) + eingebaute Presets
- Platzhalter-Material-Zuweisung
- Headless-Testskript (tests/test_rock_gen.py)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>