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>
26 KiB
Stylized Asset Generators (Blender Addons)
Dieses Repo liefert vier Extensions ueber eine URL:
Addon Panel Zweck Stylized Rock Generator Rock Gen Batch-Rocks + Textur-Bake + FBX/LOD-Export Stylized Tree Generator Tree Gen Baeume/Palmen/Bueschen/Kakteen (Geometry Nodes) mit Wachstums-Stufen Stylized Grass Generator Grass Gen Gras/Blumen/Farne mit Wind-UV fuer SimpleGrassWindStylized Asset Utils Asset Utils Handgebaute Assets auf die Konvention bringen Ein Blender-Extension-Repo kann mehrere Extensions ausliefern —
server-generatelistet jedes Zip indist/. Ein „Check for Updates" aktualisiert also alle vier.
Panel-Aufbau (alle vier Addons)
Jedes Addon hat oben im N-Panel nur das, was man bei jedem Asset anfasst - Vorlage, Name, den grossen Erzeugen-Knopf, Zufall. Alles andere sitzt in nummerierten, eingeklappten Unter-Panels in der Reihenfolge des Arbeitsablaufs:
| Addon | Unter-Panels |
|---|---|
| Rock Gen | 1 Benennung & Groesse · 2 Form · 3 Detail & Cleanup · 4 Shading · 5 Vertex-Farben · 6 UV/LOD/Material · 7 Batch & Transform · 8 FBX-Export · 9 Textur-Bake |
| Tree Gen | 1 Wachstum · 2 Blattwerk · 3 Zusatz-Ebenen · 4 Export |
| Grass Gen | 1 Form · 2 Haltung · 3 Batch & Budget · 4 Kanal-Belegung |
| Asset Utils | 1 Vorbereiten · 2 Vertex-Farben · 3 Benennung · 4 Pruefen · 5 Export |
Schalter, die ein ganzes Unter-Panel an- und ausknipsen (Vertex-Farben backen, Wachstums-Stufen), sitzen als Haekchen im Panel-Kopf - so sieht man den Zustand, ohne aufzuklappen.
In den Generatoren sind alle Unter-Panels zugeklappt, weil es Einstellungen sind,
die man selten aendert. In Asset Utils ist jedes Unter-Panel ein Arbeitsschritt;
1, 2 und 4 macht man bei jedem Asset und bleiben deshalb offen. tests/test_panels.py
haelt diese Absicht fest, damit sie nicht versehentlich verrutscht.
Falle beim Bauen: Unter-Panels brauchen dieselbe bl_category wie das
Eltern-Panel - sonst landen sie in einem anderen Tab und sind praktisch
unsichtbar. Und das Eltern-Panel muss vor seinen Kindern registriert werden,
sonst findet Blender die bl_parent_id nicht.
EcoGame-Konventionen (alle Addons)
Abgestimmt auf A:\eco\EcoGame (UE 5.8). Kurzfassung:
Benennung
- Felsen:
Fels_<Form>_<Klasse>— Form = Buchstabe (A, B, …), Klasse =S/M/L/XL. Die Klasse setzt eine Basis-Groesse (S=0.45, M=1.0, L=1.9, XL=3.2) und ist damit ein bewusst anderes Asset — gemessen: S 0.85 m, M 1.9 m, L 3.5 m, XL 6.0 m. Davon strikt getrennt ist die Zufalls-Streuung (scale_min/max): die variiert nur die FORM und wird von „Gesamtgroesse konstant halten" auf konstantes Volumen normiert (1.11× statt 1.92×), damit sie sich nicht mit den ScaleMin/Max der Engine multipliziert. - Baeume:
<Art>_<Variante>_S<Stufe>, z. B.Birke_01_S1…Birke_01_S4. Zusatz-Ebenen haengen hinten an:_Leaf,_Frucht. - Texturen:
<name>_albedound<name>_normal— mehr nicht.
Textur-Bake
-
Nur Albedo + Normal. Roughness ist im Master-Material eine Zahl, keine Textur.
-
AO/Cavity wird ins Albedo multipliziert (Option „AO ins Albedo einrechnen", Staerke regelbar). Dunkle Ritzen und helle Platten stecken im Farbbild — das traegt den Stylized-Look. Separate Rough-/AO-Paesse sind Default aus.
-
Plattenstil (Genshin-Referenz): Die Textur besteht aus wenigen grossen, fast leeren Platten mit schmalen dunklen Fugen — das Detail steckt in der Fuge, nicht in der Flaeche. Regler:
Plattengroesse(kleiner = groessere Platten),Fugenbreite(klein = harte Fuge, flache Platte),Platten flach(1 = Flaeche nahezu einfarbig). Ein dichtes Zellmuster ueber die ganze Oberflaeche erschlaegt die Form und passt NICHT zu diesem Look. -
Vertex-Farb-Layout v2 (kanal-getrennt), Attribut
Cavity:Kanal Inhalt R Cavity pur — 1 = offene Flaeche, 0 = tiefe Fuge (ohne Hoehen-Verlauf) G Moos-/Schmutzmaske — 1 = hier waechst was (Oberseite + Fugennaehe + Noise) B Hoehen-Verlauf — 0 = Unterseite, 1 = oben A 1 (Reserve) Getrennt statt eingebacken: der erdige Boden-Saum am Stein-Fuss und die Moosfarbe werden pro Material-Instanz geregelt, nicht im Mesh festgelegt. Regler:
Cavity-Staerke,Weichzeichnen,Moos-Menge,Moos-Aufbruch,Moos-Seed. G alternativ als Teil-Maske: HakenG = Teil-Maske (Shells)markiert getrennte Mesh-Teile statt Moos — der oberste/breiteste Teil bekommt 1, der Rest 0. Assets, die aus mehreren Objekten mit Strg+J verbunden wurden (Pilz = Hut + Stiel), lassen sich damit EXAKT trennen statt ueber Normalen geschaetzt. Ein Material toent dann beide Teile unterschiedlich — kein zweiter Material-Slot noetig. Einteilige Meshes bleiben unmarkiert (G=0). Der ButtonVertex-Cavity auf Auswahlbackt das Layout auf JEDES markierte Mesh — also auch auf handgebaute Assets, nicht nur auf generierte Steine. Verifiziert: R ohne Hoehenabhaengigkeit (unten 0.62 / oben 0.59), B steigt sauber (0.08 -> 0.92), G oben staerker (0.20 -> 0.57), A konstant 1, Seed aendert die Verteilung, und alle Kanaele ueberleben den FBX-Roundtrip. -
Texturfreie Alternative — Vertex-Cavity: Statt zu baken laesst sich die Cavity in die Vertex-Farben schreiben (Attribut
Cavity, ueberlebt den FBX-Roundtrip verlustfrei — gemessen 0.250..0.947 vor und nach dem Import). Das Material braucht dann keine Textur:Base Color = Farbton x VertexColor, dazu Kantenlicht (Fresnel) und Schattentint. Vorteil gegenueber Triplanar: die dunklen Fugen sitzen auf den ECHTEN Kanten des Meshes statt darueberzuschweben. Grenze: die Aufloesung haengt an der Vertex-Dichte — fuer flaechige Platten reicht sie, fuer feine Struktur nicht. -
1024 px reicht fuer stylized Formen.
-
Tileable (4D-Torus) passt zum triplanar mappenden Master-Material.
Mesh
- Echte Meter, Ursprung unten-mittig, FBX pro Asset bzw. LOD-Gruppe.
- UV1 Lightmap ist Default aus — EcoGame beleuchtet dynamisch.
- Meshes brauchen keine eigenen Materialien; in UE bekommt alles die Material-Instanz vom Master. Ein Platzhalter im FBX ist okay.
- Scale-Randomisierung nur fuer die Form (nicht-uniform) nutzen, nicht fuer die Gesamtgroesse — sonst multipliziert sie sich mit ScaleMin/Max der Engine.
Export-Haertung (Rock Gen)
Drei Dinge passieren beim FBX-Export jetzt automatisch. Alles laeuft auf temporaeren Kopien - die Szene bleibt unveraendert.
1. Ursprung wird erzwungen (keine Option). Jedes Objekt wandert an den
Welt-Ursprung, der Ursprung sitzt unten-mittig der Bounding-Box. Anlass: das
25er-Set trug seine Szenen-Rasterpositionen (bis 20 m) im Mesh, die Steine
schwebten im Spiel neben ihrem Platzierungspunkt. Nachgemessen am
reimportierten FBX: Bbox-Mitte 0.000/0.000, min.Z 0.000.
2. Flache Steine werden hingelegt (Flache Steine hinlegen, Default an).
Die kuerzeste Bbox-Achse wird nach oben gedreht. Gedreht wird nur, wenn es etwas
bringt - bei einem 2.53/1.40/1.54-Stein wuerde Kippen die Form nur willkuerlich
drehen. Im Spiel gibt es nur zufaelligen Yaw, die gebackene Ausrichtung ist also
endgueltig.
3. UCX-Kollision (UCX-Kollision mitexportieren, Default an). Konvexe Huelle
als UCX_<Name> im selben FBX, Unreal nimmt sie als Simple Collision. Budget
ueber UCX max. Verts (Default 32).
Drei Fallen, die dabei aufgefallen sind:
- Blender haengt an Kopien
.001an. Unreal ordnet die Kollision aber ueber den exakten Mesh-Namen zu - das Original bekommt fuer die Dauer des Exports einen Hilfsnamen, die Kopie den echten. bmesh.from_meshbringt die Originalflaechen mit,convex_hulllegt seine Huelle dann obendrauf: gemessen 16-21 offene Kanten. Es duerfen nur die Punkte eingelesen werden.- Jede Vereinfachung der Huelle schneidet Ecken ab, sie wird dadurch kleiner als der Stein - eine Kollision kleiner als das Mesh laesst den Spieler einsinken. Deshalb wird sie danach exakt so weit aufgeblasen, dass wieder alles hineinpasst.
LOD-Gruppen + Vertex-Farben (war offen, jetzt geklaert)
Ging nicht: der LOD-Zweig sprang komplett am Cavity-Bake vorbei, LOD-Gruppen kamen ohne Farbattribut aus dem Export - auf keiner der vier Stufen. Jetzt wird auf LOD0 gebacken, bevor dupliziert wird; das Decimate interpoliert die Farben mit. Wuerde je Stufe neu gebacken, haette jede Stufe ihre eigene Cavity und der LOD-Wechsel wuerde poppen. Nach dem FBX-Roundtrip gemessen:
| Stufe | Verts | R-Bereich |
|---|---|---|
| LOD0 | 40 | 0.30..1.00 |
| LOD1 | 21 | 0.41..0.92 |
| LOD2 | 11 | 0.45..0.92 |
| LOD3 | 6 | 0.49..0.88 |
Dazu die zweite Falle: ob.matrix_world = Identity loescht die Transformation
nicht, wenn das Objekt ein Eltern-Objekt hat - Blender rechnet eine lokale
Gegen-Matrix aus. Bei einer LOD-Gruppe auf (13/-7.5/2.2) landete das Mesh dadurch
bei genau MINUS dieser Position. matrix_basis und matrix_parent_inverse
muessen direkt genullt werden.
Die UCX-Huelle haengt bewusst neben dem LodGroup-Empty, nicht darunter - Unreal wuerde jedes Kind der Gruppe als weitere LOD-Stufe lesen.
Stylized Asset Utils
Fuer alles, was von Hand gebaut wird (Pilze, Baumstumpf, Erzfels, Props) und deshalb nicht durch einen Generator laeuft. Panel in fuenf einklappbaren Schritten:
- Vorbereiten — Rotation/Scale anwenden, Ursprung unten-mittig, optional Normalen neu berechnen. Damit steht das Asset in UE bei Scale 1 auf dem Boden.
- Vertex-Farben — dasselbe Layout wie beim Rock Generator
(
R= Cavity,G= Maske,B= Hoehe,A= 1).Gwahlweise als Teil-Maske: bei Assets, die mit Strg+J aus mehreren Objekten verbunden wurden (Pilz = Hut + Stiel), bekommt der oberste Teil 1 und der Rest 0 — exakt statt geschaetzt. Ein Material toent damit beide Teile, ein zweiter Material-Slot entfaellt. Einteilige Meshes bleiben unmarkiert. - Benennung — Auswahl nach
<Basis>_<NN>umbenennen, Mesh-Daten ziehen mit. - Pruefen — Asset-Check: nicht angewendete Transforms, Ursprung nicht unten, Tri-Budget, fehlende UV/Vertex-Farben, lose Vertices, Custom Split Normals. Details in der System-Konsole.
- Export — FBX je Mesh mit
colors_type='SRGB', Triangulate und waehlbarem Smoothing.
Falle, die dabei auffiel: bpy.ops.paint.vertex_color_set braucht den
Vertex-Paint-Modus und scheitert im Object-Mode mit „poll() failed". Steht es mit
vertex_color_dirt im selben try, wird der ganze Bake stillschweigend
uebersprungen. Die Initialisierung laeuft deshalb direkt ueber Python.
Stylized Grass Generator
Gras-, Blumen- und Farn-Bueschel. Der Kern ist die Wind-UV:
- UV0.V = 0 an der Wurzel, 1 an der Spitze — genau die Maske, die UEs
SimpleGrassWindals WindWeight braucht. Ohne sie rutscht der Halm beim Wehen vom Boden weg oder bewegt sich gar nicht. Am ZielmaterialM_Grassgeprueft: es liestTextureCoordinate, aber keineVertexColor— deshalb liefert der Generator die Maske PRIMAER ueber die UV. Die Assets funktionieren damit ohne Materialaenderung. - Vertex-Farben zusaetzlich (nicht als einzige Quelle):
R= Kopie der Windmaske ·G= Variation je HALM ·B= AO (unten dunkel).Gist die Ebene unter dem Biom-Tint, den die Engine ueberPerInstanceCustomData 0/1pro Instanz setzt — im Material multiplizieren, nicht ersetzen. - Presets:
gras,gras_hoch,steppengras,farn,blume. - Tri-Budget-Warnung (Default 400 laut
ASSETS.mdfuer Gras/Blume). Gemessen: ein Standard-Bueschel mit 14 Halmen = 112 Tris. - Ursprung unten-mittig (
min_z = 0.0000), UV und Vertex-Farben ueberleben den FBX-Roundtrip.
Stylized Tree Generator
Proportionen: gemessen, nicht geschaetzt
Drei Presets sahen falsch aus. Die Ursachen wurden gemessen bzw. belegt, nicht
geraten - tests/test_proportionen.py haelt die Werte fest:
| Was | vorher (gemessen) | jetzt | Quelle fuer den Zielwert |
|---|---|---|---|
| Palmenkrone | Radius/Hoehe 0.11 - ein Mop-Kopf am Stamm | 0.30 | tree-gen palm.py (Weber&Penn): Wedellaenge 0.3 x Stamm; TreeIt-Referenzpalme 3.3 m bei 4.33 m = 0.38 |
| Busch | 1.81 m hoch, 0.84 m breit (B/H 0.46) - ein Baeumchen | 1.20 m hoch, 2.0 m breit (B/H 1.6) | Strauch = mehrere Stiele ab Boden, kein Leittrieb; gemessen nach Hoehe UND Breite |
| Setzling | relativ 2.4x dicker als der Altbaum (r/H 0.025 gegen 0.0104) | proportional gleich schlank | McMahon, elastische Aehnlichkeit: Hoehe ~ Durchmesser^(2/3), also Faktor 0.16^1.5 |
Der Wedel-Winkel kam dazu: mit Branch Up 0 standen die Wedel als gerade
Antennenspeichen ab. tree-gen gibt down_angle 60 + curve 40 an - also
schraeg raus und dann ueberbiegen. Gemessen steigen die Wedel jetzt 1.1 m ueber
den Ansatz und kippen dann ab.
Nicht jede Pflanze waechst wie ein Laubbaum (GROWTH_OVERRIDES):
- Palme: Einkeimblaettrige haben kein Dickenwachstum - erst der Durchmesser, dann die Hoehe. „Once a palm stem emerges from the apical meristem, its diameter is fixed for life" (UF/IFAS ENH1212). Der Setzling ist ein kurzer Stumpf in fast voller Dicke, kein Schoessling.
- Kaktus: Sukkulent, gleiche Logik. Ausserdem ohne Arme - Saguaros bilden die erst mit 50-70 Jahren, bei rund 2 m Hoehe (NPS).
- Weide: haengt erst, wenn die Zweige lang genug sind. Junge Weiden wachsen aufrecht; mit dem allgemeinen Droop reichten ihre Zweige 0.27 m unter den Stammfuss und das Asset waere in UE geschwebt.
Dabei gefunden: Branch Count = 0 schaltete die Aeste nicht ab -
dieselbe Falle wie seinerzeit bei Sub Count (Curve to Points klemmt Count
auf mindestens 1). Fuer die Sub-Ebene gab es laengst einen Geometry-Switch, fuer
die Hauptaeste nicht. Jetzt liegen beide Ebenen hinter demselben Schalter.
Ebenfalls gefunden: im Busch-Preset stand Branch Count zweimal im selben
Dict - der zweite Eintrag hat den ersten still ueberschrieben.
Parametrischer Geaest-Generator (Stamm + Aeste + Sub-Aeste) als Geometry-Nodes- Gruppe. Blaetter/Krone macht man selbst — das Addon liefert die Struktur.
- Presets:
baum,palme,busch,tanne,eiche,birke,weide,toter_baum,kaktus— die Silhouette steuert die Kronenform (Crown Taper/Crown Bulge, Idee aus modular_tree / Weber-Penn). - Tri-Budget: alle Presets liegen unter dem Projektlimit (Baum ≤2500,
Busch ≤800). Stellschrauben:
Detail(Segmente) undSides/Branch Sides/Sub Sides(Profilaufloesung je Ebene — Stamm rund, Zweige nur Dreiecke). - Wachstums-Stufen: Haken setzen + Anzahl waehlen → Setzling bis ausgewachsen, gleicher Seed = dieselbe Baum-Identitaet (fuer Wachstums-Systeme im Spiel).
- Live bearbeiten: Nach dem Erzeugen liegen alle Regler am Modifier
GN_Tree— im Viewport ziehen, der Baum aktualisiert sich sofort. - Blattwerk: Ein Blatt-/Billboard-Objekt als Blatt-Card waehlen (z. B. eine
Diamond-Plane mit Alpha-Textur) → der Button streut es auf die Zweige und legt
das Ergebnis als
<Name>_Leafmit identischem Ursprung ab. Gefiltert wird ueber den Astradius (Max Radius), damit keine Blaetter am Stamm kleben. Ohne Card bleibt_Leafleer zum Selbermodellieren. - Tri-Budget: Der Blattwerk-Button meldet
Stamm + Blatt = Summeund warnt bei Ueberschreitung. Default-Dichte 150 haelt auch das schwerste Preset (Eiche, 1428 Tris) mit 2460 von 2500 Tris im Budget. - Export: „Modifier anwenden" friert das Ergebnis als normales Mesh ein.
v1.1.0: Aeste folgen jetzt der Elternkurve (Tangent/Normal aus Curve to
Points, Goldener Winkel = Phyllotaxis) statt einer aus Weltkoordinaten
gerechneten Richtung — Sub-Aeste standen vorher wie Nadeln quer zum Ast.
Neu: Tip Blunt (Baum laeuft spitz aus, Kaktus endet stumpf).
Der kaktus nutzt Droop Curve fuer den Saguaro-Ellbogen (Arm laeuft flach raus
und knickt dann steil hoch). Offen ist dort nur, dass die Rippen (Ribs) im
Shading kaum sichtbar sind.
Stylized Rock Generator (Blender Addon)
Batch-Generator fuer stylized Rocks in Blender, ausgelegt auf den Export nach Unreal Engine 5 ueber FBX.
Pipeline pro Rock: Basis-Mesh (Cube / Ico-Sphere) → Subdivision Surface → Displace mit prozeduraler Noise-Textur (Voronoi / Clouds / Distorted Noise) → zweistufiges Decimate → Limited Dissolve → Normalen-Reparatur → UV0 (Smart Project) + UV1 (Lightmap) → optional Bevel/Weighted Normal, Material, LOD-Set, randomisierte Skalierung/Rotation.
Getestet mit Blender 5.1.2 (Minimum laut bl_info: 4.2).
Installation
stylized_rock_generator.pyherunterladen.- Blender → Edit → Preferences → Add-ons → Install… → die
.pywaehlen. - Haken bei Stylized Rock Generator setzen.
- Panel: View3D → Sidebar (N) → Reiter "Rock Gen".
Update: einfach die neue .py erneut installieren (gleicher Modulname) oder das
Repo lokal ziehen und den Addon-Pfad in den Preferences auf den Repo-Ordner
zeigen lassen.
Installation als Extension (via URL, mit Auto-Update)
Ein Repo, vier Extensions.
blender --command extension server-generatescanntdist/und listet jedes gefundene Zip - eine URL liefert in Blender alle vier Addons.build.ps1ruft das mit--htmlauf, dann entsteht zusaetzlich eineindex.htmlzum Durchblaettern (auf einem statischen Webserver; Gitea liefert rohes HTML als Text aus).Kein Versions-Archiv: zwei Zips derselben Extension-ID nebeneinander sind nicht der Weg, eine alte Version zum Zurueckrollen bereitzuhalten - server-generate warnt dann (
archive found with duplicates ... conflicting blender versions). Mehrere Versionen einer ID sind nur erlaubt, wenn sie verschiedene Blender-Bereiche abdecken. Alte Version wieder her: pergit checkoutdes Zips.
Ab Blender 4.2 / 5.x als Remote-Extension-Repository – einmal die URL eintragen, danach gehen Updates per Klick.
-
Das Gitea-Repo muss oeffentlich sein (sonst kann Blender die Raw-URL nicht ohne Login laden).
-
Blender → Edit → Preferences → Get Extensions → oben rechts das Dropdown → Repositories → „Add Remote Repository".
-
Als URL eintragen:
https://git.d4rkst3r.de/D4rkst3r/stylized-rock-generator/raw/branch/main/dist/index.json -
„Check for Updates" aktivieren, bestaetigen. Die Extension erscheint in der Liste → Install.
Updaten (Maintainer-Seite):
versioninblender_manifest.toml(undbl_info["version"]in der.py) erhoehen../build.ps1(oderblender --command extension build …+… server-generate …).git add -A && git commit -m "vX.Y.Z" && git push.- Nutzer: in Blender Check for Updates → Update.
Das gebaute Zip + index.json liegen in dist/ und werden bewusst mitversioniert,
damit die Raw-URL sie ausliefert.
Features
- Basis-Formen: Wuerfel, Quader oder Ico-Sphere, einstellbare Subsurf-Stufen.
Der Quader hat frei einstellbare
Quader-Proportionen(X/Y/Z) plusProportions-Streuung— damit entstehen flache Platten und langgestreckte Riegel statt nur runder Brocken. Gemessen bei Proportion (2.0, 1.5, 0.35): 3.43 / 2.56 / 0.79 m — Z also 23 % von X. Die Proportionen werden auf gleiches Volumen normiert — „M" bedeutet damit bei jeder Form dasselbe. Eine Platte ist dann flacher UND breiter als ein Wuerfel derselben Klasse, aber nicht schwerer; ihre laengste Kante ist entsprechend groesser (das ist Absicht, kein Fehler). Die Proportionen werden auf die MESH-DATEN angewendet, nicht auf das Objekt: der Displace nutzt globale Texturkoordinaten, eine Objekt-Skalierung wuerde das Rauschen mitverzerren statt die Form zu aendern. - Noise/Displace: Voronoi / Clouds / Distorted Noise, Scale + Staerke, Seed. Seed-Variation ueber einen moderaten Welt-Offset (±25) vor dem Displace-Apply – Blenders prozedurale Texturen haben keinen echten Seed-Parameter.
- Cleanup: zweistufiges Decimate + Limited Dissolve, danach
normals_make_consistent(verhindert eingefallene/dunkle Flaechen). - UV fuer Unreal: UV0 (Smart Project) fuer Material-Texturen, UV1 (Lightmap) als separater, nicht ueberlappender Kanal fuer Static-Mesh-Lightmaps.
- Hard-Surface (optional): Bevel + Weighted Normal fuer einen "clean" Kantenlook.
- Material (Platzhalter): weist pro Rock ein Material zu und rotiert durch eine kleine Palette (Granite/Basalt/Sandstone/Mossy), damit nichts materiallos exportiert wird.
- LOD-Set: erzeugt LOD0–LODn als LOD-Gruppe fuer Unreal (siehe unten).
- Presets: eingebaute Presets (Kleiner Kiesel, Grosser Bruchfels, Lava-Rock)
plus eigene Presets als JSON (
rock_presets.jsonneben dem Addon). - Batch: synchron fuer kleine Mengen, ab
modal_threshold(Default 25) automatisch modal mit Progress-Bar – die UI bleibt bedienbar, ESC bricht ab. - Robustheit: Faellt ein einzelner Rock aus (z. B. 0 Faces nach zu aggressivem Decimate), wird nur dieser uebersprungen und aufgeraeumt, der Rest des Batches bleibt erhalten. Fehler landen in der System-Konsole.
LOD-Export nach Unreal
Blenders FBX-Exporter kennt keine eigene LOD-Option. Unreal erkennt eine
LOD-Gruppe aber, wenn das Eltern-Empty die Custom Property
fbx_type = "LodGroup" traegt und die LOD-Meshes in Reihenfolge (LOD0…LODn)
darunter geparentet sind. Genau das erzeugt der Generator.
Beim FBX-Export darauf achten:
- Custom Properties aktivieren (sonst geht
fbx_typeverloren). - Nur die LOD-Gruppe (Empty + Kinder) selektieren,
use_selectionan.
Beim Import in Unreal:
- Im FBX-Import-Dialog Import LODs aktivieren.
Referenz: Importing Static Mesh LODs Using FBX (UE Docs).
Tests
Alles auf einmal:
pwsh -File run_tests.ps1
Einzeln geht weiterhin blender --background --python tests/<datei>.py,
gefiltert .\run_tests.ps1 -Filter panels.
Warum der Runner existiert. Die Tests lagen einzeln herum und wurden nur beim Bauen des jeweiligen Features gestartet. Beim Aufraeumen der Panels stellte sich heraus, dass fuenf davon still veraltet waren: sie prueften gegen Objekt-Namen aus der Zeit vor dem Benennungssystem (
Rock_stattFels_A_M_01), gegen fest verdrahtete Zip-Versionen, oder zaehlten die spaeter dazugekommenen_Leaf-Objekte mit. Sie haetten eine echte Regression nicht gemeldet. Die drei Muster, die das ausgeloest haben, sind jetzt vermieden: Objekte ueber die Differenz vorher/nachher finden statt ueber ein Namens-Praefix, Zips per glob statt mit fester Version, und Zusatz-Ebenen beim Zaehlen herausfiltern.
| Datei | prueft |
|---|---|
tests/test_proportionen.py |
Baum-Proportionen: Palmenkrone, Strauch-Breite, Setzling-Schlankheit, Branch Count 0 |
tests/test_export_robust.py |
Export am reimportierten FBX: Ursprung erzwungen, flach = liegend, UCX geschlossen/umschliessend/im Budget, LOD+Vertex-Farben |
tests/test_panels.py |
Alle vier Addons: registrieren, jedes Panel zeichnet, Unter-Panels im richtigen Tab, jede Property irgendwo erreichbar |
tests/test_tree_addon.py |
Tree-Addon: Presets, Wachstums-Stufen, UVs, Modifier-Apply |
tests/test_ecogame_rock.py |
Fels-Benennung, Bake liefert nur _albedo/_normal, AO im Albedo |
tests/test_ecogame_tree.py |
Baum-Benennung <Art>_<Variante>_S<Stufe>, Ursprung, Lightmap-Default |
tests/test_randomize.py |
Zufalls-Funktion von Rock und Tree, _Leaf/_Frucht mit gleichem Ursprung |
tests/test_leaves.py |
Blattwerk: Streuung, Ursprung, Tri-Budget, leeres _Leaf ohne Card |
tests/test_rock_classes.py |
Groessen-Klassen S/M/L/XL unterscheiden sich, Streuung bleibt formbezogen |
Die Suiten erwarten die gebauten Zips in dist/ bzw. lesen die .py direkt.
Erzeugt 3 Rocks, prueft je Rock: keine losen Vertices, manifold, Normalen nach aussen (signed volume > 0), UV0 + UV1 vorhanden, und gibt eine Zusammenfassung (Vertex-/Face-Count) aus. Exit-Code 0 = alles bestanden, 1 = Fehler.
Changelog v2.3.0
- Textur-Bake auf Zell-Look umgestellt: Voronoi „Distance to Edge" liefert hand-painted Zellen mit dunklen Outlines statt organischem fBm-Rauschen. Neu regelbar: Grundfarbe und Zellgroesse. Weiterhin nahtlos tileable.
Changelog v2.2.0
- Textur-Bake-Button: backt ein nahtlos tileables Stylized-Rock-Set
(BaseColor / Normal / Roughness / AO) als PNG. Nahtlos durch 4D-Torus-
Projektion der UV (
cos/sinvon U und V) → tilet in beide Richtungen ohne Naht, ideal fuer Triplanar in Unreal. - Anleitung zur UE-Material-Verdrahtung: siehe docs/UE_Material_Triplanar.md.
Changelog v2.1.0
- FBX-Export-Button (UE-ready): exportiert jeden Rock / jede LOD-Gruppe als
eigene FBX mit
use_custom_props=True(fuerfbx_type=LodGroup), Triangulate und passendem Smoothing (EDGEbei Auto-Smooth, sonstFACE). UE-Import-Tipp: Normal Import Method auf „Import Normals" stellen, „Import LODs" an. - Shading-Toggle: Faceted / Smooth / Auto-Smooth-nach-Winkel.
- Pro-Rock-Varianz: Noise-Scale & Displace-Staerke zwischen Min/Max plus optionale nicht-uniforme Skalierung → ein Batch wirkt variantenreich.
- Boden abflachen (Bisect) + Origin unten-mittig → Rocks stehen in UE plan auf.
Changelog v2.0.0
Gehaertet & erweitert gegenueber v1.0.0:
- Bugfix:
smart_project(angle_limit=…)ist in Blender 4.x/5.x in Radiant ([0, 1.5708]) – der alte Wert66.0war ungueltig. Jetztradians(66°). - Bugfix:
dissolve_limited(angle_limit=…)erwartet Radiant; der Grad-Wert wurde ungewandelt durchgereicht → uebermaessiges Dissolve. Jetztradians(dissolve_angle). - Bugfix: Der Lightmap-Kanal wurde vor
lightmap_packnicht als aktiver UV-Layer gesetzt → UV0 konnte ueberschrieben werden. Jetzt explizit gesetzt, UV0 danach wieder als Render-Kanal. - Fehlerbehandlung um jeden
bpy.ops.*-Aufruf; einzelne Rock-Fehler brechen den Batch nicht mehr ab. - Nicht-blockierender modaler Batch-Modus mit Progress-Bar.
- Bevel + Weighted Normal als Toggle.
- LOD-Set als
fbx_type=LodGroup-Gruppe. - Preset-System (JSON) mit Panel-Dropdown.
- Platzhalter-Material-Zuweisung.