From 2bf2f907bfb62be055127f5f9546e1f994c27f08 Mon Sep 17 00:00:00 2001 From: D4rkst3r Date: Mon, 3 Aug 2026 08:23:42 +0200 Subject: [PATCH] Rock Gen 2.16.0: Bruchstuecke (Punkt 4) + Erz-Stueck (Punkt 4a) 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: _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 _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 --- README.md | 35 +++++ blender_manifest.toml | 2 +- dist/index.html | 6 +- dist/index.json | 8 +- dist/stylized_rock_generator-2.15.0.zip | Bin 29580 -> 0 bytes dist/stylized_rock_generator-2.16.0.zip | Bin 0 -> 32002 bytes stylized_rock_generator.py | 195 +++++++++++++++++++++++- tests/test_bruchstuecke.py | 160 +++++++++++++++++++ 8 files changed, 397 insertions(+), 9 deletions(-) delete mode 100644 dist/stylized_rock_generator-2.15.0.zip create mode 100644 dist/stylized_rock_generator-2.16.0.zip create mode 100644 tests/test_bruchstuecke.py diff --git a/README.md b/README.md index 488c4d7..69e1eb1 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,40 @@ Gemessen (dicht, ~2700 Tris): Erz-Anteil 0.08 → 4 %, 0.18 → 9 %, 0.35 → 15 der Oberflaeche. A faellt auf 0.00 und erreicht 1.00, und die Maske ueberlebt den FBX-Roundtrip. +## Bruchstuecke (Steine zerschlagen) + +Kein Laufzeit-Fracturing im Spiel: die Teile werden beim Anschlagen als +Physik-Actors gespawnt. Sie entstehen deshalb hier als vollwertige Assets. +Knopf **In Bruchstuecke zerlegen** arbeitet auf der Auswahl und liefert +`_Piece_01..NN`. Regler: `Bruchstuecke` (2-4), `Bruch-Seed`, +`Ein Stueck mit Erz`, `Mutterstein ausblenden`. + +Jedes Teil bekommt: Vertex-Layout v2, Ursprung unten-mittig, die **gleichen +Material-Slots** wie der Mutterstein (die UE-Skripte mappen darueber) und beim +Export eine eigene `UCX_`-Huelle. + +**Punkt 4a:** mit `Ein Stueck mit Erz` heisst ein zufaelliges Teil +`_Piece_Erz` und traegt Erz-Adern im A-Kanal. Alle anderen Teile behalten +A = 1.0. Ob das Erz-Stueck gespawnt wird, entscheidet die Loot-Logik im Spiel. + +**Wie die Bruchkanten zusammenpassen:** 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 - die Bruchflaechen passen zusammen, ohne dass man sie abstimmen muesste. +Bewusst ohne das Cell-Fracture-Addon: das muesste beim User aktiviert sein und +haengt an Operator-Kontext, bmesh laeuft immer. + +> **Die entscheidende Falle.** Jeder Schnitt muss **sofort** geschlossen werden, +> und zwar ueber genau die Kanten, die `bisect_plane` als `geom_cut` zurueckgibt. +> Der naheliegende Weg - am Ende alle Randkanten suchen und fuellen - erzeugte +> Kanten mit vier Flaechen; raeumte man die ab, blieben Loecher. Aufgefallen ist +> das am **Volumen**: die Teile kamen zusammen auf 72.7 % des Muttersteins, +> weil `calc_volume` bei offenen Meshes Unsinn liefert. Jetzt sind es **100.2 %** +> bei 2, 3 und 4 Teilen, mit 0 offenen und 0 non-manifold Kanten. + +`tests/test_bruchstuecke.py` prueft genau diesen Volumen-Vergleich - er ist +zugleich das Warnsignal fuer kaputte Topologie. + ## Smooth & dicht Knopf im Form-Panel: setzt Unterteilung 5, Decimate 0.40/0.80 und Auto-Smooth. @@ -484,6 +518,7 @@ gefiltert `.\run_tests.ps1 -Filter panels`. | Datei | prueft | |---|---| | `tests/test_proportionen.py` | Baum-Proportionen: Palmenkrone, Strauch-Breite, Setzling-Schlankheit, Branch Count 0 | +| `tests/test_bruchstuecke.py` | Bruchstuecke: Volumen 100 % des Muttersteins, dichte Topologie, genau ein Erz-Stueck, Material-Slots, Ursprung, UCX je Teil | | `tests/test_erz.py` | Erz-Maske: A=1.0 ohne Erz, Anteil monoton, Set-Namen/Groessen, Einstellungen zurueckgesetzt, FBX-Roundtrip, Tri-Fenster | | `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** | diff --git a/blender_manifest.toml b/blender_manifest.toml index 12a6276..4602900 100644 --- a/blender_manifest.toml +++ b/blender_manifest.toml @@ -1,7 +1,7 @@ schema_version = "1.0.0" id = "stylized_rock_generator" -version = "2.15.0" +version = "2.16.0" name = "Stylized Rock Generator" tagline = "Batch-Generator fuer stylized Rocks mit UE5-Export" maintainer = "D4rkst3r" diff --git a/dist/index.html b/dist/index.html index 474edf9..f514219 100644 --- a/dist/index.html +++ b/dist/index.html @@ -40,14 +40,14 @@ 4.9KB - stylized_rock_generator-2.15.0 + stylized_rock_generator-2.16.0 Stylized Rock Generator Batch-Generator fuer stylized Rocks mit UE5-Export link 4.2.0 - ~ all all - 28.9KB + 31.3KB stylized_tree_generator-1.25.0 @@ -61,6 +61,6 @@ -

Built 2026-08-03, 06:13

+

Built 2026-08-03, 06:23

diff --git a/dist/index.json b/dist/index.json index d2d3988..0514d69 100644 --- a/dist/index.json +++ b/dist/index.json @@ -57,7 +57,7 @@ "id": "stylized_rock_generator", "name": "Stylized Rock Generator", "tagline": "Batch-Generator fuer stylized Rocks mit UE5-Export", - "version": "2.15.0", + "version": "2.16.0", "type": "add-on", "maintainer": "D4rkst3r", "license": [ @@ -73,9 +73,9 @@ "Mesh", "Modeling" ], - "archive_url": "./stylized_rock_generator-2.15.0.zip", - "archive_size": 29580, - "archive_hash": "sha256:f57604a8176506626352d61e79a5a449f8d1aedced3aeed3a288a1abe5efcd51" + "archive_url": "./stylized_rock_generator-2.16.0.zip", + "archive_size": 32002, + "archive_hash": "sha256:cb9cb1d36073da86d67d5997b9266a7d3192587591995a0fd59f6fa12f57b3e1" }, { "schema_version": "1.0.0", diff --git a/dist/stylized_rock_generator-2.15.0.zip b/dist/stylized_rock_generator-2.15.0.zip deleted file mode 100644 index a1106a8ebdad7558ea892a166a7dc53963cb4897..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29580 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 bgKGYNY)3^|aESjbg8b_~|HgNx|IGdi17_gt diff --git a/dist/stylized_rock_generator-2.16.0.zip b/dist/stylized_rock_generator-2.16.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..fb7240264a03c13620bdb4f0224269131b0396e3 GIT binary patch literal 32002 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 J{eLb%{{wmkv4Q{q literal 0 HcmV?d00001 diff --git a/stylized_rock_generator.py b/stylized_rock_generator.py index d3b818b..810f587 100644 --- a/stylized_rock_generator.py +++ b/stylized_rock_generator.py @@ -1,7 +1,7 @@ bl_info = { "name": "Stylized Rock Generator", "author": "D4rkst3r", - "version": (2, 15, 0), + "version": (2, 16, 0), "blender": (4, 2, 0), "location": "View3D > Sidebar > Rock Gen", "description": ( @@ -1007,6 +1007,26 @@ class RockGenSettings(PropertyGroup): description="Andere Verteilung der Nuggets bei gleicher Form", ) + # --- Bruchstuecke --- + piece_count: IntProperty( + name="Bruchstuecke", default=3, min=2, max=4, + description="In wie viele Teile ein Stein zerfaellt", + ) + piece_with_ore: BoolProperty( + name="Ein Stueck mit Erz", default=False, + description=("Ein zufaelliges Bruchstueck heisst _Piece_Erz und " + "traegt Erz im A-Kanal. Ob es gespawnt wird, entscheidet " + "die Loot-Logik im Spiel"), + ) + piece_seed: IntProperty( + name="Bruch-Seed", default=0, min=0, max=9999, + description="Andere Bruchlinien bei gleicher Form", + ) + piece_hide_source: BoolProperty( + name="Mutterstein ausblenden", default=True, + description="Blendet den ungebrochenen Stein aus, statt ihn zu loeschen", + ) + part_mask_from_shells: BoolProperty( name="G = Teil-Maske (Shells)", default=False, description=("Statt der Moos-Maske: getrennte Mesh-Teile markieren. " @@ -1565,6 +1585,169 @@ def _safe_filename(name): return "".join(c for c in name if c.isalnum() or c in keep).strip() or "Rock" +def _voronoi_cells(me, punkte): + """Zerlegt ein Mesh in Voronoi-Zellen. Liefert je Zelle ein neues Mesh. + + Verfahren: eine Zelle ist der Schnitt aller Halbraeume. Fuer jedes andere + Zentrum wird an der Mittelsenkrechten zwischen beiden Zentren geschnitten und + die abgewandte Seite verworfen. Der Clou: benachbarte Zellen schneiden an + GENAU DERSELBEN Ebene - dadurch passen die Bruchflaechen zusammen, ohne dass + man sie aufeinander abstimmen muesste. + + Bewusst ohne das Cell-Fracture-Addon: das muesste beim User aktiviert sein + und arbeitet ueber Operatoren mit Kontext-Anforderungen. bmesh laeuft immer. + + Wichtig ist, JEDEN Schnitt sofort zu schliessen und dafuer genau die Kanten + zu nehmen, die `bisect_plane` als `geom_cut` zurueckgibt. Der Umweg ueber + "am Ende alle Randkanten suchen und fuellen" war nicht verlaesslich: er hat + Kanten mit vier Flaechen erzeugt, und wenn man die abgeraeumt hat, blieben + Loecher. Ein offenes Bruchstueck ist als Physik-Actor unbrauchbar. + """ + zellen = [] + for i, pi in enumerate(punkte): + bm = bmesh.new() + bm.from_mesh(me) + for j, pj in enumerate(punkte): + if i == j: + continue + normale = pj - pi + laenge = normale.length + if laenge < 1e-6: + continue + normale = normale / laenge + mitte = (pi + pj) * 0.5 + ergebnis = bmesh.ops.bisect_plane( + bm, geom=bm.verts[:] + bm.edges[:] + bm.faces[:], + plane_co=mitte, plane_no=normale, + clear_outer=True, # alles jenseits der Ebene verwerfen + use_snap_center=False, + ) + if not bm.faces: + break + # Genau die Schnittkanten schliessen - das ist die Bruchflaeche. + schnitt = [g for g in ergebnis.get("geom_cut", []) + if isinstance(g, bmesh.types.BMEdge) and g.is_valid] + if schnitt: + try: + bmesh.ops.edgeloop_fill(bm, edges=schnitt) + except (TypeError, ValueError, RuntimeError): + bmesh.ops.holes_fill(bm, edges=schnitt, sides=0) + + if not bm.faces: + bm.free() + zellen.append(None) + continue + + # Sicherheitsnetz, falls ein Schnitt doch etwas offen gelassen hat. + rand = [e for e in bm.edges if len(e.link_faces) == 1] + if rand: + bmesh.ops.holes_fill(bm, edges=rand, sides=0) + + gross = [f for f in bm.faces if len(f.verts) > 4] + if gross: + bmesh.ops.triangulate(bm, faces=gross) + bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:]) + bm.normal_update() + + neu = bpy.data.meshes.new(me.name + "_cell%d" % i) + bm.to_mesh(neu) + bm.free() + zellen.append(neu) + return zellen + + +class ROCKGEN_OT_fracture(Operator): + """Zerlegt die ausgewaehlten Steine in Bruchstuecke. + + Kein Laufzeit-Fracturing im Spiel: die Teile werden beim Anschlagen als + Physik-Actors gespawnt. Deshalb entstehen sie hier als vollwertige Assets - + Vertex-Layout v2, Ursprung unten-mittig, gleiche Material-Slots, und beim + Export bekommt jedes Teil seine eigene UCX-Huelle. + """ + bl_idname = "rockgen.fracture" + bl_label = "In Bruchstuecke zerlegen" + bl_description = ("Erzeugt _Piece_01..NN mit zusammenpassenden " + "Bruchkanten. Optional ein Stueck mit Erz-Adern") + bl_options = {'REGISTER', 'UNDO'} + + def execute(self, context): + s = context.scene.rock_gen_settings + _ensure_object_mode(context) + quellen = [o for o in context.selected_objects if o.type == 'MESH'] + if not quellen: + self.report({'ERROR'}, "Keine Mesh-Objekte ausgewaehlt.") + return {'CANCELLED'} + + rng = random.Random(s.piece_seed) + gesamt, leer = 0, 0 + + for src in quellen: + me = src.data + co = [v.co for v in me.vertices] + if not co: + continue + lo = Vector((min(c.x for c in co), min(c.y for c in co), + min(c.z for c in co))) + hi = Vector((max(c.x for c in co), max(c.y for c in co), + max(c.z for c in co))) + + # Zentren im Inneren streuen, mit Abstand zum Rand: sonst entstehen + # hauchduenne Splitter statt brauchbarer Brocken. + n = s.piece_count + punkte = [Vector(( + lo.x + (hi.x - lo.x) * (0.2 + 0.6 * rng.random()), + lo.y + (hi.y - lo.y) * (0.2 + 0.6 * rng.random()), + lo.z + (hi.z - lo.z) * (0.2 + 0.6 * rng.random()), + )) for _ in range(n)] + + zellen = _voronoi_cells(me, punkte) + # Punkt 4a: ein Stueck traegt optional das Erz. Ob es gespawnt wird, + # entscheidet die Loot-Logik im Spiel. + erz_idx = rng.randrange(n) if s.piece_with_ore else -1 + + for i, zelle in enumerate(zellen): + if zelle is None or len(zelle.polygons) == 0: + leer += 1 + if zelle is not None: + bpy.data.meshes.remove(zelle) + continue + ist_erz = (i == erz_idx) + name = "%s_Piece_%s" % (src.name, + "Erz" if ist_erz else "%02d" % (i + 1)) + zelle.name = name + ob = bpy.data.objects.new(name, zelle) + context.collection.objects.link(ob) + ob.matrix_world = src.matrix_world.copy() + + # Gleiche Material-Slots wie der Mutterstein - die UE-Skripte + # mappen ueber die Slot-Namen. + for mat in me.materials: + zelle.materials.append(mat) + + _apply_shading(context, ob, s) + if s.bake_vertex_cavity: + merker = s.bake_ore + s.bake_ore = ist_erz + try: + _bake_vertex_cavity(context, ob, s) + except RockGenError as exc: + print("[RockGen] Cavity auf %s: %s" % (name, exc)) + finally: + s.bake_ore = merker + _set_origin_bottom(context, ob) + gesamt += 1 + + if s.piece_hide_source: + src.hide_set(True) + + if leer: + self.report({'WARNING'}, "%d Bruchstueck(e), %d Zelle(n) leer " + "(Zentren lagen zu dicht)." % (gesamt, leer)) + else: + self.report({'INFO'}, "%d Bruchstueck(e) erzeugt." % gesamt) + return {'FINISHED'} + + class ROCKGEN_OT_dense_preset(Operator): """Stellt auf smooth und dicht um (~2700 Tris statt ~620).""" bl_idname = "rockgen.dense_preset" @@ -2389,6 +2572,15 @@ class VIEW3D_PT_rock_vcol(_RockSub): sub.prop(s, "ore_seed") sub.separator() sub.operator("rockgen.ore_set", icon='MOD_EXPLODE') + layout.separator() + box = layout.box() + box.label(text="Bruchstuecke", icon='MOD_BUILD') + row = box.row(align=True) + row.prop(s, "piece_count") + row.prop(s, "piece_seed", text="") + box.prop(s, "piece_with_ore") + box.prop(s, "piece_hide_source") + box.operator("rockgen.fracture", icon='MOD_BUILD') col.label(text="R=Cavity G=%s B=Hoehe A=%s" % ("Teil-Maske" if s.part_mask_from_shells else "Moos", "Erz" if s.bake_ore else "1.0"), @@ -2503,6 +2695,7 @@ classes = ( OBJECT_OT_bake_rock_textures, ROCKGEN_OT_bake_cavity_selection, ROCKGEN_OT_dense_preset, + ROCKGEN_OT_fracture, ROCKGEN_OT_ore_set, ROCKGEN_OT_randomize, ROCKGEN_OT_preset_save, diff --git a/tests/test_bruchstuecke.py b/tests/test_bruchstuecke.py new file mode 100644 index 0000000..5000a63 --- /dev/null +++ b/tests/test_bruchstuecke.py @@ -0,0 +1,160 @@ +"""Bruchstuecke (Wunschliste 4 und 4a). + +Kein Laufzeit-Fracturing im Spiel: die Teile werden beim Anschlagen als +Physik-Actors gespawnt. Sie muessen deshalb vollwertige Assets sein. + +Der wichtigste Test ist der VOLUMEN-Vergleich: die Teile muessen zusammen den +Mutterstein ergeben. Er ist auch das Warnsignal fuer schlechte Topologie - +`calc_volume` liefert bei offenen Meshes Unsinn. Genau daran ist eine fruehere +Fassung aufgefallen: sie kam auf 72.7 %, weil das Fuellen der Bruchflaechen +Loecher hinterliess. + +Aufruf: blender --background --factory-startup --python tests/test_bruchstuecke.py +""" +import os +import sys +import tempfile +import importlib.util + +import bpy +import bmesh + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +spec = importlib.util.spec_from_file_location( + "rg", os.path.join(ROOT, "stylized_rock_generator.py")) +rg = importlib.util.module_from_spec(spec) +sys.modules["rg"] = rg +spec.loader.exec_module(rg) +rg.register() + +fails = [] + + +def topologie(ob): + bm = bmesh.new() + bm.from_mesh(ob.data) + offen = sum(1 for e in bm.edges if len(e.link_faces) == 1) + nm = sum(1 for e in bm.edges if len(e.link_faces) > 2) + draht = sum(1 for e in bm.edges if len(e.link_faces) == 0) + bm.free() + return offen, nm, draht + + +def volumen(ob): + bm = bmesh.new() + bm.from_mesh(ob.data) + bm.transform(ob.matrix_world) + v = abs(bm.calc_volume(signed=True)) + bm.free() + return v + + +for o in list(bpy.data.objects): + bpy.data.objects.remove(o, do_unlink=True) + +s = bpy.context.scene.rock_gen_settings +s.batch_count = 1 +s.use_modal = False +s.assign_material = True # Material-Slots muessen mitwandern +s.generate_lods = False +s.bake_vertex_cavity = True +bpy.ops.rockgen.dense_preset() +bpy.ops.object.generate_rocks_batch() + +mutter = [o for o in bpy.context.scene.objects if o.type == 'MESH'][0] +v_mutter = volumen(mutter) +slots_mutter = [m.name for m in mutter.data.materials] + +for anzahl in (2, 3, 4): + for o in list(bpy.context.scene.objects): + if "_Piece_" in o.name: + bpy.data.objects.remove(o, do_unlink=True) + mutter.hide_set(False) + for o in bpy.context.scene.objects: + o.select_set(o is mutter) + bpy.context.view_layer.objects.active = mutter + + s.piece_count = anzahl + s.piece_with_ore = True + s.piece_seed = 2 + bpy.ops.rockgen.fracture() + + teile = [o for o in bpy.context.scene.objects if "_Piece_" in o.name] + if len(teile) != anzahl: + fails.append("%d Teile angefordert, %d bekommen" % (anzahl, len(teile))) + + v_teile = sum(volumen(o) for o in teile) + quote = 100.0 * v_teile / v_mutter if v_mutter else 0.0 + print("%d Teile: Volumen %.1f %% des Muttersteins" % (anzahl, quote)) + # Die Teile muessen den Stein ergeben. Toleranz fuer die triangulierten + # Bruchflaechen; deutlich weniger heisst Loecher oder verlorene Zellen. + if not (97.0 <= quote <= 103.0): + fails.append("%d Teile ergeben %.1f %% des Muttersteins (erwartet 97-103)" + % (anzahl, quote)) + + erz = [o for o in teile if o.name.endswith("_Piece_Erz")] + if len(erz) != 1: + fails.append("%d Teile: %d Stueck mit Erz, erwartet genau 1" + % (anzahl, len(erz))) + + for ob in sorted(teile, key=lambda o: o.name): + offen, nm, draht = topologie(ob) + lay = ob.data.color_attributes.get("Cavity") + a = [c.color[3] for c in lay.data] if lay else [] + co = [ob.matrix_world @ v.co for v in ob.data.vertices] + unten = ob.matrix_world.translation.z - min(c.z for c in co) + + if offen or nm or draht: + fails.append("%s: offen %d, non-manifold %d, Draht %d - als " + "Physik-Actor unbrauchbar" % (ob.name, offen, nm, draht)) + if lay is None: + fails.append("%s: kein Vertex-Layout v2" % ob.name) + elif ob.name.endswith("_Piece_Erz"): + if max(a) < 0.9 or min(a) > 0.01: + fails.append("%s: traegt keine Erz-Maske (A %.2f..%.2f)" + % (ob.name, min(a), max(a))) + else: + if min(a) < 0.999: + fails.append("%s: A ist nicht 1.0 (min %.2f) - nur das " + "Erz-Stueck darf Erz tragen" % (ob.name, min(a))) + if abs(unten) > 0.01: + fails.append("%s: Ursprung nicht unten (%.3f m)" % (ob.name, unten)) + if [m.name for m in ob.data.materials] != slots_mutter: + fails.append("%s: Material-Slots %s statt %s - die UE-Skripte " + "mappen darueber" + % (ob.name, [m.name for m in ob.data.materials], + slots_mutter)) + +# --- Export: je Teil eine eigene UCX-Huelle ------------------------------ +OUT = tempfile.mkdtemp() +s.export_dir = OUT +s.export_selected_only = False +s.export_ucx = True +bpy.ops.object.export_rocks_fbx() + +dateien = sorted(f for f in os.listdir(OUT) if f.lower().endswith(".fbx")) +piece_fbx = [f for f in dateien if "_Piece_" in f] +print("") +print("Export: %d FBX, davon %d Bruchstuecke" % (len(dateien), len(piece_fbx))) +if not piece_fbx: + fails.append("Bruchstuecke wurden nicht exportiert") +else: + bpy.ops.wm.read_factory_settings(use_empty=True) + bpy.ops.import_scene.fbx(filepath=os.path.join(OUT, piece_fbx[0])) + meshes = [o for o in bpy.context.scene.objects if o.type == 'MESH'] + hull = [o for o in meshes if o.name.startswith("UCX_")] + koerper = [o for o in meshes if not o.name.startswith("UCX_")] + print(" %s: %d Mesh, %d UCX" % (piece_fbx[0], len(koerper), len(hull))) + if not hull: + fails.append("%s: keine UCX-Huelle - fuer die Physik-Bruchstuecke " + "brauchen wir echte Konvexe" % piece_fbx[0]) + if koerper and not koerper[0].data.color_attributes: + fails.append("%s: Vertex-Farben nach dem Roundtrip weg" % piece_fbx[0]) + +print("") +if fails: + print("ERGEBNIS: %d FEHLER" % len(fails)) + for x in fails: + print(" - " + x) + sys.exit(1) +print("ERGEBNIS: ALLE CHECKS OK")