U5.5 Lane-Fassung: LOD für den Meshy-Kohlenbeißer
Lane-Kopie mit 4.998 statt 20.714 Dreiecken aus dem Generator (Nähte verschweißt, Collapse, Skin-Gewichte bleiben), LODGroup aus den Namen, Wechsel unter rund 10 % Bildhöhe; Porträts erzwingen die volle Fassung. Stresstest 35 Kohlenbeißer: Mid 109,8 -> 120,2 fps, Karte 93,9 -> 103,8 (starr 133,3 / 106,4). Tests grün, Fingerabdrücke unverändert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
@ -74,7 +74,7 @@
|
||||||
{
|
{
|
||||||
"check": "mesh_names_unique",
|
"check": "mesh_names_unique",
|
||||||
"ok": true,
|
"ok": true,
|
||||||
"detail": "['KohlenbeisserBody']"
|
"detail": "['KohlenbeisserBody_LOD0', 'KohlenbeisserBody_LOD1']"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"check": "material_slots_filled",
|
"check": "material_slots_filled",
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
{
|
{
|
||||||
"check": "triangles_match_godot",
|
"check": "triangles_match_godot",
|
||||||
"ok": true,
|
"ok": true,
|
||||||
"detail": "20714 fbx / 20714 godot"
|
"detail": "25712 fbx / 25712 godot"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"check": "one_armature",
|
"check": "one_armature",
|
||||||
|
|
@ -144,7 +144,7 @@
|
||||||
{
|
{
|
||||||
"check": "roundtrip_triangles",
|
"check": "roundtrip_triangles",
|
||||||
"ok": true,
|
"ok": true,
|
||||||
"detail": "20714 / 20714"
|
"detail": "25712 / 25712"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"check": "roundtrip_materials",
|
"check": "roundtrip_materials",
|
||||||
|
|
@ -254,21 +254,28 @@
|
||||||
2048
|
2048
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"unit": 0.009999999776482582
|
"unit": 0.009999999776482582,
|
||||||
|
"lod": {
|
||||||
|
"lod0_triangles": 20714,
|
||||||
|
"lod1_triangles": 4998,
|
||||||
|
"lod1_vertices": 2501,
|
||||||
|
"welded_triangles": 20714,
|
||||||
|
"lod0_screen": 0.2
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"inputs_sha256": {
|
"inputs_sha256": {
|
||||||
"tools/meshy/g01/figure.json": "858bf47dc277a8a3a9f280d3f51a156b575d8abd091b083abf0cf2a32dc2277c",
|
"tools/meshy/g01/figure.json": "8e642064d739ba4ed94d18233037bb44ecbf023e08ccc076605a8059b8f13211",
|
||||||
"assets-source/meshy/g01/kohlenbeisser-skelett.glb": "f5379bc92f77f42235b45decc5dfab26428c6649ea3a17ca7b33809fe4dcd568",
|
"assets-source/meshy/g01/kohlenbeisser-skelett.glb": "f5379bc92f77f42235b45decc5dfab26428c6649ea3a17ca7b33809fe4dcd568",
|
||||||
"assets-source/meshy/g01/kohlenbeisser-animationen.glb": "16ede0d7afb86a46d658265ed7df4d1b1b0c9c5171af6de9257e6c764a55cb48"
|
"assets-source/meshy/g01/kohlenbeisser-animationen.glb": "16ede0d7afb86a46d658265ed7df4d1b1b0c9c5171af6de9257e6c764a55cb48"
|
||||||
},
|
},
|
||||||
"source_sha256": "124688e799e0508e58af53f5346857e5404d49875d6600cbb974afe1b1e5796e",
|
"source_sha256": "9eb17a4e3dc7029b7031f3be85f6676877c521788835137eb199c352c5b35aa4",
|
||||||
"removed_modifiers": 0,
|
"removed_modifiers": 0,
|
||||||
"kind": "skinned",
|
"kind": "skinned",
|
||||||
"fps": 24.0,
|
"fps": 24.0,
|
||||||
"objects": 2,
|
"objects": 3,
|
||||||
"meshes": {
|
"meshes": {
|
||||||
"KohlenbeisserBody": {
|
"KohlenbeisserBody_LOD0": {
|
||||||
"mesh": "KohlenbeisserBody",
|
"mesh": "KohlenbeisserBody_LOD0",
|
||||||
"triangles": 20714,
|
"triangles": 20714,
|
||||||
"vertices": 22962,
|
"vertices": 22962,
|
||||||
"ngons": 0,
|
"ngons": 0,
|
||||||
|
|
@ -303,6 +310,43 @@
|
||||||
0.3833
|
0.3833
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"KohlenbeisserBody_LOD1": {
|
||||||
|
"mesh": "KohlenbeisserBody_LOD1",
|
||||||
|
"triangles": 4998,
|
||||||
|
"vertices": 2501,
|
||||||
|
"ngons": 0,
|
||||||
|
"materials": [
|
||||||
|
"AI_Kohlenbeisser"
|
||||||
|
],
|
||||||
|
"uv_layers": [
|
||||||
|
"UVMap"
|
||||||
|
],
|
||||||
|
"color_attributes": [],
|
||||||
|
"active_color": null,
|
||||||
|
"custom_normals": false,
|
||||||
|
"normals_unit_length": true,
|
||||||
|
"bad_normals": 0,
|
||||||
|
"degenerate_triangles": 0,
|
||||||
|
"shape_keys": 0,
|
||||||
|
"skinned": true,
|
||||||
|
"scale": [
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"bounds_unity": {
|
||||||
|
"min": [
|
||||||
|
-0.8581,
|
||||||
|
0.0003,
|
||||||
|
-0.3892
|
||||||
|
],
|
||||||
|
"max": [
|
||||||
|
0.8593,
|
||||||
|
1.3498,
|
||||||
|
0.3856
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"armatures": {
|
"armatures": {
|
||||||
|
|
@ -342,14 +386,14 @@
|
||||||
"empties": {},
|
"empties": {},
|
||||||
"bounds_unity": {
|
"bounds_unity": {
|
||||||
"min": [
|
"min": [
|
||||||
-0.857,
|
-0.8581,
|
||||||
0.0,
|
0.0,
|
||||||
-0.388
|
-0.3892
|
||||||
],
|
],
|
||||||
"max": [
|
"max": [
|
||||||
0.8576,
|
0.8593,
|
||||||
1.35,
|
1.35,
|
||||||
0.3833
|
0.3856
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"clips": [
|
"clips": [
|
||||||
|
|
@ -425,7 +469,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"expected_from_godot": {
|
"expected_from_godot": {
|
||||||
"triangles": 20714,
|
"triangles": 25712,
|
||||||
"bones": 25,
|
"bones": 25,
|
||||||
"clips": [
|
"clips": [
|
||||||
"idle",
|
"idle",
|
||||||
|
|
@ -439,8 +483,8 @@
|
||||||
},
|
},
|
||||||
"meshes_with_ngons": {},
|
"meshes_with_ngons": {},
|
||||||
"meshes_without_uv": [],
|
"meshes_without_uv": [],
|
||||||
"triangles": 20714,
|
"triangles": 25712,
|
||||||
"fbx": "Assets/Luneraria/Art/Characters/kohlenbeisser.fbx",
|
"fbx": "Assets/Luneraria/Art/Characters/kohlenbeisser.fbx",
|
||||||
"fbx_bytes": 2936524,
|
"fbx_bytes": 3262700,
|
||||||
"ok": true
|
"ok": true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,9 @@ ModelImporter:
|
||||||
additiveReferencePoseFrame: 0
|
additiveReferencePoseFrame: 0
|
||||||
isReadable: 1
|
isReadable: 1
|
||||||
meshes:
|
meshes:
|
||||||
lODScreenPercentages: []
|
lODScreenPercentages:
|
||||||
|
- 0.25
|
||||||
|
- 0.01
|
||||||
globalScale: 1
|
globalScale: 1
|
||||||
meshCompression: 0
|
meshCompression: 0
|
||||||
addColliders: 0
|
addColliders: 0
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Luneraria.EditorTools
|
||||||
/// <summary>Raised on the figure at the hit frame of attack and ability clips.</summary>
|
/// <summary>Raised on the figure at the hit frame of attack and ability clips.</summary>
|
||||||
public const string ContactEvent = "OnLuneContact";
|
public const string ContactEvent = "OnLuneContact";
|
||||||
|
|
||||||
public override uint GetVersion() { return 4; }
|
public override uint GetVersion() { return 5; }
|
||||||
|
|
||||||
void OnPreprocessModel()
|
void OnPreprocessModel()
|
||||||
{
|
{
|
||||||
|
|
@ -48,6 +48,28 @@ namespace Luneraria.EditorTools
|
||||||
importer.resampleCurves = false;
|
importer.resampleCurves = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// U5.5: a figure with a lane copy (meshes <body>_LOD0/_LOD1, Unity builds the LODGroup
|
||||||
|
/// from the names) switches to it below the screen height the generator names; the lane
|
||||||
|
/// copy is never culled, so a figure never vanishes at map zoom.
|
||||||
|
/// </summary>
|
||||||
|
void OnPostprocessModel(GameObject root)
|
||||||
|
{
|
||||||
|
if (!assetPath.StartsWith(ArtRoot) || !assetPath.EndsWith(".fbx"))
|
||||||
|
return;
|
||||||
|
LODGroup group = root.GetComponentInChildren<LODGroup>();
|
||||||
|
ExportReport report = ExportReport.ForModel(assetPath);
|
||||||
|
var lod = report?.Data["generator"]?["lod"];
|
||||||
|
if (group == null || lod == null)
|
||||||
|
return;
|
||||||
|
LOD[] lods = group.GetLODs();
|
||||||
|
if (lods.Length != 2)
|
||||||
|
return;
|
||||||
|
lods[0].screenRelativeTransitionHeight = (float)lod["lod0_screen"];
|
||||||
|
lods[1].screenRelativeTransitionHeight = 0f;
|
||||||
|
group.SetLODs(lods);
|
||||||
|
}
|
||||||
|
|
||||||
void OnPreprocessAnimation()
|
void OnPreprocessAnimation()
|
||||||
{
|
{
|
||||||
if (!assetPath.StartsWith(ArtRoot) || !assetPath.EndsWith(".fbx"))
|
if (!assetPath.StartsWith(ArtRoot) || !assetPath.EndsWith(".fbx"))
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,10 @@ namespace Luneraria.UI
|
||||||
foreach (Transform node in model.GetComponentsInChildren<Transform>(true))
|
foreach (Transform node in model.GetComponentsInChildren<Transform>(true))
|
||||||
node.gameObject.layer = Layer;
|
node.gameObject.layer = Layer;
|
||||||
Library.Materials?.Dress(model, 2);
|
Library.Materials?.Dress(model, 2);
|
||||||
|
// A figure with a lane copy (U5.5) shows its full mesh: the portrait is a close-up, and
|
||||||
|
// the LOD choice of a model rendered in the frame it was made in left the card empty.
|
||||||
|
foreach (LODGroup group in model.GetComponentsInChildren<LODGroup>(true))
|
||||||
|
group.ForceLOD(0);
|
||||||
ShowDetail(model);
|
ShowDetail(model);
|
||||||
// Skinned figures stand in their idle pose (Godot preview("idle", .4)).
|
// Skinned figures stand in their idle pose (Godot preview("idle", .4)).
|
||||||
if (entry.Controller != null)
|
if (entry.Controller != null)
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,17 @@ Hinweis: Die Projektdateien des .NET-Harness (`tools/dotnet/*/*.csproj`) fehlten
|
||||||
| Bekannte Unterschiede | keine im Verhalten. Geometrie und Textur der Figur wechseln (Meshy statt Phase-4); Anatomie/Gesicht/Haar aus dem generierten Modell, nicht aus Künstler-Sculpts. Lava-Glut pauschal (keine Emission-Map). Schatten der Figur nur mit Tiefen-Bias |
|
| Bekannte Unterschiede | keine im Verhalten. Geometrie und Textur der Figur wechseln (Meshy statt Phase-4); Anatomie/Gesicht/Haar aus dem generierten Modell, nicht aus Künstler-Sculpts. Lava-Glut pauschal (keine Emission-Map). Schatten der Figur nur mit Tiefen-Bias |
|
||||||
| Commits | `luneraria/u5.5-pilot` = `c386206` |
|
| Commits | `luneraria/u5.5-pilot` = `c386206` |
|
||||||
|
|
||||||
|
## U5.5 · Lane-Fassung (LOD)
|
||||||
|
|
||||||
|
| Punkt | Ergebnis |
|
||||||
|
| --- | --- |
|
||||||
|
| Tests | EditMode 29/29, PlayMode 14/14 (Verify A–I 718/0), Player-Selbsttest 30/30, Asset-Prüfung 20/0 |
|
||||||
|
| Parität | Fingerabdrücke unverändert (`DCE95C96556F3A1A`, `7B8E43AEFC0D60C5`) |
|
||||||
|
| Inhalt | Kohlenbeißer mit Lane-Fassung (4.998 statt 20.714 Dreiecke, LODGroup aus dem Export), Porträts in voller Fassung |
|
||||||
|
| Leistung | Stresstest 35 Kohlenbeißer: Mid 109,8 → 120,2 fps (starr 133,3), Karte 93,9 → 103,8 fps (starr 106,4). Rohdaten `logs/u5.5-lod/` |
|
||||||
|
| Bild | `screenshots/u5.5-lod/` (Figur, vier Spielmomente, 14 Kampfmomente) |
|
||||||
|
| Commits | `luneraria/u5.5-lod` |
|
||||||
|
|
||||||
## Ausblick
|
## Ausblick
|
||||||
|
|
||||||
Der Pilot entscheidet über eine Serie weiterer Meshy-Figuren (Kosten je Figur, Lizenz, Stilgleichheit). Offen bleiben außerdem Künstler-Sculpts für Anatomie/Gesicht/Haar, LOD und Material-Atlanten sowie die Build-Module für Windows und Linux.
|
Der Pilot entscheidet über eine Serie weiterer Meshy-Figuren (Kosten je Figur, Lizenz, Stilgleichheit). Offen bleiben außerdem Künstler-Sculpts für Anatomie/Gesicht/Haar, LOD und Material-Atlanten sowie die Build-Module für Windows und Linux.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Port-Status · Champions of Luneraria in Unity
|
# Port-Status · Champions of Luneraria in Unity
|
||||||
|
|
||||||
Stand: 9. Oktober 2026 (U5.5-pilot).
|
Stand: 9. Oktober 2026 (U5.5, Lane-Fassung).
|
||||||
|
|
||||||
Referenz ist der Godot-Stand `luneraria/g3` (`1b540f2`) in `../saumwacht-godot`; er wird nicht mehr verändert. Engine: Unity 6.3 LTS (6000.3.20f1), Renderer URP. HDRP ist ausgeschlossen, bis ein Vergleich mit einer echten Szene etwas anderes nahelegt.
|
Referenz ist der Godot-Stand `luneraria/g3` (`1b540f2`) in `../saumwacht-godot`; er wird nicht mehr verändert. Engine: Unity 6.3 LTS (6000.3.20f1), Renderer URP. HDRP ist ausgeschlossen, bis ein Vergleich mit einer echten Szene etwas anderes nahelegt.
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ Zielplattformen sind Fedora 44 und Windows 11; macOS ist die Entwicklungsplattfo
|
||||||
| U2 · Unity-Spielwelt | **fertig**: U2A Blender→FBX-Pipeline (9 Assets geprüft), U2B G1-Karte mit Materialsystem, U2C fester Takt und Ansichten (bildratenunabhängig nachgewiesen), U2D vollständige Bot-Partien sichtbar und gleich dem Kern; danach Batch-Import aller 86 Modelle, Einheiten mit eigenen Modellen | [U2-WORLD.md](U2-WORLD.md) |
|
| U2 · Unity-Spielwelt | **fertig**: U2A Blender→FBX-Pipeline (9 Assets geprüft), U2B G1-Karte mit Materialsystem, U2C fester Takt und Ansichten (bildratenunabhängig nachgewiesen), U2D vollständige Bot-Partien sichtbar und gleich dem Kern; danach Batch-Import aller 86 Modelle, Einheiten mit eigenen Modellen | [U2-WORLD.md](U2-WORLD.md) |
|
||||||
| U3 · G3-HUD portieren | **fertig** (`luneraria/u3`): UI Toolkit, Sichtmodell mit Privatsphäre, menschlicher Sitz, alle HUD-Bereiche, Eingabe und Befehle, Prüfung 718/0, 14 G3-Motive, Spieltest, Leistung mit HUD | [U3-UI.md](U3-UI.md) |
|
| U3 · G3-HUD portieren | **fertig** (`luneraria/u3`): UI Toolkit, Sichtmodell mit Privatsphäre, menschlicher Sitz, alle HUD-Bereiche, Eingabe und Befehle, Prüfung 718/0, 14 G3-Motive, Spieltest, Leistung mit HUD | [U3-UI.md](U3-UI.md) |
|
||||||
| U4 · Netzwerk | **fertig** (`luneraria/u4` = `769e622`): LuneSession (Protokoll 4), TCP-Transport, Startbildschirm Host/Join, 43+12 Prüfungen, Mindestumfang M4. Nachtrag (`luneraria/u4-nachtrag`, in U5.3 zusammengeführt): Startbildschirm in der Szene, „Menü“ führt dorthin zurück | [U4-NETWORK.md](U4-NETWORK.md) |
|
| U4 · Netzwerk | **fertig** (`luneraria/u4` = `769e622`): LuneSession (Protokoll 4), TCP-Transport, Startbildschirm Host/Join, 43+12 Prüfungen, Mindestumfang M4. Nachtrag (`luneraria/u4-nachtrag`, in U5.3 zusammengeführt): Startbildschirm in der Szene, „Menü“ führt dorthin zurück | [U4-NETWORK.md](U4-NETWORK.md) |
|
||||||
| U5 · Visuelle Neuausrichtung (Vertical Slice Mid-Lane) | **fertig** (`luneraria/u5` = `2c1686b`, Stufen `luneraria/u5.2`): 6 PBR-Sätze, Surface-Shader mit Albedo/Normal/ORM, Stufen Lane/Rand, Hit- und Turm-VFX, 133/180 fps. **U5.3** (`luneraria/u5.3` = `07fa457`): Gebäude, Boss und Ringborkes Rinde auf PBR (11 Sätze); Bildfehler aus U5 behoben (doppelte Einfärbung, Datenkarten als sRGB, Streifen, bleichender Treffer-Flash, Nebel), Helligkeit und Grün wieder auf U3-Niveau **U5.4** (`luneraria/u5.4` = `4883d95`): Surface-Materialien für alle 146 Figurenmaterialien (Metalle metallisch, Randlicht, Struktur in den Porträts), SSAO (abschaltbar), Leistung −13 % Karte / −16 % Mid **U5.5-pilot** (`luneraria/u5.5-pilot` = `c386206`): Meshy-Figur für den Kohlenbeißer `g01` (Pipeline `tools/meshy/`, UV-Material mit Lava-Glut, Schatten ohne Normalen-Versatz), GPU-Batched-Skinning, Figuren-Stress −21 % Mid / −13 % Karte gegenüber Phase-4 | [U5-VISUAL.md](U5-VISUAL.md) |
|
| U5 · Visuelle Neuausrichtung (Vertical Slice Mid-Lane) | **fertig** (`luneraria/u5` = `2c1686b`, Stufen `luneraria/u5.2`): 6 PBR-Sätze, Surface-Shader mit Albedo/Normal/ORM, Stufen Lane/Rand, Hit- und Turm-VFX, 133/180 fps. **U5.3** (`luneraria/u5.3` = `07fa457`): Gebäude, Boss und Ringborkes Rinde auf PBR (11 Sätze); Bildfehler aus U5 behoben (doppelte Einfärbung, Datenkarten als sRGB, Streifen, bleichender Treffer-Flash, Nebel), Helligkeit und Grün wieder auf U3-Niveau **U5.4** (`luneraria/u5.4` = `4883d95`): Surface-Materialien für alle 146 Figurenmaterialien (Metalle metallisch, Randlicht, Struktur in den Porträts), SSAO (abschaltbar), Leistung −13 % Karte / −16 % Mid **U5.5-pilot** (`luneraria/u5.5-pilot` = `c386206`): Meshy-Figur für den Kohlenbeißer `g01` (Pipeline `tools/meshy/`, UV-Material mit Lava-Glut, Schatten ohne Normalen-Versatz), GPU-Batched-Skinning, Figuren-Stress −21 % Mid / −13 % Karte gegenüber Phase-4; **Lane-Fassung** (`luneraria/u5.5-lod`): 5.000-Dreiecke-LOD, Abstand −10 % Mid / −2 % Karte | [U5-VISUAL.md](U5-VISUAL.md) |
|
||||||
|
|
||||||
QA je Meilenstein: [PORT-QA.md](PORT-QA.md).
|
QA je Meilenstein: [PORT-QA.md](PORT-QA.md).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -389,3 +389,42 @@ Wirkung: Der Kohlenbeißer zeigt gehämmerte Platten und glühende Lava in den F
|
||||||
- **UV-Nähte statt geteilter Schatten-Normalen.** `ShadowNormalScale 0` vermeidet die Lichtkanten, nimmt der Figur aber den Normalen-Versatz im Schattenwurf (Tiefen-Bias allein).
|
- **UV-Nähte statt geteilter Schatten-Normalen.** `ShadowNormalScale 0` vermeidet die Lichtkanten, nimmt der Figur aber den Normalen-Versatz im Schattenwurf (Tiefen-Bias allein).
|
||||||
- **Geometrie ist teurer** als die starre Phase-4-Figur (−22 % Mid bei 35 Kopien mit GPU-Skinning). Abhilfe wäre LOD oder eine reduzierte Schattenkopie; beides ist offen.
|
- **Geometrie ist teurer** als die starre Phase-4-Figur (−22 % Mid bei 35 Kopien mit GPU-Skinning). Abhilfe wäre LOD oder eine reduzierte Schattenkopie; beides ist offen.
|
||||||
- **Build-Module** für Windows und Linux fehlen weiterhin (PORT-STATUS).
|
- **Build-Module** für Windows und Linux fehlen weiterhin (PORT-STATUS).
|
||||||
|
|
||||||
|
## U5.5 · Lane-Fassung des Kohlenbeißers (LOD)
|
||||||
|
|
||||||
|
Stand 9. Oktober 2026, Zweig `luneraria/u5.5-lod` (auf `luneraria/u5.5-pilot`). Antwort auf die offene Grenze oben: Die Meshy-Figur hat jetzt eine vereinfachte Fassung für Lane-Zoom und Karte.
|
||||||
|
|
||||||
|
### Umfang
|
||||||
|
|
||||||
|
- **Lane-Kopie im Generator** (`build_figure.py`, `lane_lod`, Regel `lod` in `figure.json`): Kopie des Körpers, die an den UV-Nähten getrennten Eckpunkte verschweißt, auf 5.000 Dreiecke reduziert (Collapse; UVs, Material und Skin-Gewichte bleiben), Normalen glatt mit harten Kanten ab 50°. Nach dem Reduzieren werden entartete und doppelt belegte Dreiecke entfernt; der FBX-Rückimport behielt von zwei Dreiecken auf denselben drei Ecken nur eines.
|
||||||
|
- `KohlenbeisserBody_LOD0` 20.714 Dreiecke / 22.962 Eckpunkte, `KohlenbeisserBody_LOD1` 4.998 / 2.501; Export 23 Prüfungen bestanden, zweiter Lauf bytegleich.
|
||||||
|
- **Unity:** Aus den Namen `_LOD0`/`_LOD1` baut der Import eine LODGroup. `LuneModelPostprocessor` (Version 5) setzt den Wechsel auf die Bildschirmhöhe aus dem Exportbericht (`generator.lod.lod0_screen` = 0,2; mit dem LOD-Bias 2 der Qualitätsstufe „Ultra“ wechselt die Figur unter rund 10 % Bildhöhe). Die Lane-Fassung wird nie ausgeblendet.
|
||||||
|
- Ein erster Wert von 0,1 ließ die Figur wegen des Bias bei Zoom 22 meist in voller Fassung; gemessen brachte er Mid nichts und auf der Karte 5 %.
|
||||||
|
- **HUD-Porträts** erzwingen die volle Fassung (`LunePortraits`, `ForceLOD(0)`). Ohne das blieben Karten und Porträts leer: Das Modell wird im selben Bild erzeugt und gerendert, die LOD-Wahl griff dabei nicht.
|
||||||
|
|
||||||
|
### Prüfung
|
||||||
|
|
||||||
|
| Test | Ergebnis |
|
||||||
|
| --- | --- |
|
||||||
|
| EditMode | 29/29 |
|
||||||
|
| PlayMode | 14/14 (6 Werkzeuge `Explicit`), Verify A–I 718/0 |
|
||||||
|
| Fingerabdrücke | `DCE95C96556F3A1A`, `7B8E43AEFC0D60C5`, unverändert, `same_as_core` |
|
||||||
|
| Asset-Prüfung Unity | `kohlenbeisser` 20 Prüfungen, 0 Fehler |
|
||||||
|
| Player-Selbsttest | 30/30, `logs/u5.5-lod/player-smoke.json` |
|
||||||
|
| FigureViewsTests | 1/1, Bilder `screenshots/u5.5-lod/spiel/` |
|
||||||
|
|
||||||
|
### Leistung
|
||||||
|
|
||||||
|
Figuren-Stresstest wie oben (`-luneBenchmarkRound 5 -luneBenchmarkArmy g01`, 35 Kohlenbeißer), GPU-Skinning, je vier Läufe abwechselnd, Deckel offen (`logs/u5.5-lod/player-benchmark-army-*.json`):
|
||||||
|
|
||||||
|
| Ansicht | Phase-4 (starr) | Meshy ohne LOD | Meshy mit LOD |
|
||||||
|
| --- | ---: | ---: | ---: |
|
||||||
|
| Mid-Lane nah (Zoom 22) | 133,3 | 109,8 (−18 %) | 120,2 (−10 %) |
|
||||||
|
| ganze Karte (Zoom 64) | 106,4 | 93,9 (−12 %) | 103,8 (−2 %) |
|
||||||
|
|
||||||
|
Die Lane-Fassung halbiert den Abstand in der Mid-Ansicht und schließt ihn auf der Karte fast. Der Rest liegt vor allem beim Animator (Hauptthread +0,5 ms gegenüber der starren Figur, die nicht animiert wird) und bei der GPU. Im Bild ist der Wechsel bei Lane-Zoom nicht zu sehen (Vergleich `screenshots/u5.5/spiel-nachher/04-kampf-lane.jpg` mit `u5.5-lod/spiel/04-kampf-lane.jpg`).
|
||||||
|
|
||||||
|
### Grenzen
|
||||||
|
|
||||||
|
- Der Wechsel ist hart (kein Überblenden); bei Zoom um die Schwelle kann man ihn an den Krallen sehen.
|
||||||
|
- Die Lane-Fassung trägt geglättete Normalen statt Meshys geteilter Normalen; die Normalkarte ist für die volle Fassung gebacken. Aus der Lane-Distanz fällt das nicht auf.
|
||||||
|
|
|
||||||
|
|
@ -1300,6 +1300,173 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "kohlenbeisser",
|
||||||
|
"kind": "skinned",
|
||||||
|
"ok": true,
|
||||||
|
"checks": [
|
||||||
|
{
|
||||||
|
"check": "blender_checks_passed",
|
||||||
|
"ok": true,
|
||||||
|
"detail": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "imported",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "\"Assets/Luneraria/Art/Characters/kohlenbeisser.fbx\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "import_rules_applied",
|
||||||
|
"ok": true,
|
||||||
|
"detail": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "root_transform_identity",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "\"kohlenbeisser pos (0.0000, 0.0000, 0.0000) rot (0.00, 0.00, 0.00) scale (1.0000, 1.0000, 1.0000)\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "node_transforms_axis_clean",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "mesh_names",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "triangles",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "\"25712 unity / 25712 blender \""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "material_slots",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "normals_unit_length",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "tangents_where_uv",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "uvs_where_blender_has_uv",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "vertex_colors",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "bounds_axes_scale",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "\"largest difference 0.00002 m; unity (-0.858, 0.000, -0.389) (0.859, 1.350, 0.386)\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "skinned_mesh",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "bone_names KohlenbeisserBody_LOD0",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "root_bone KohlenbeisserBody_LOD0",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "\"Root\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "bone_names KohlenbeisserBody_LOD1",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "root_bone KohlenbeisserBody_LOD1",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "\"Root\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "generic_avatar",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "\"kohlenbeisserAvatar\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"check": "clips",
|
||||||
|
"ok": true,
|
||||||
|
"detail": "[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"facts": {
|
||||||
|
"triangles": 25712,
|
||||||
|
"renderers": 2,
|
||||||
|
"meshes_without_uv_and_tangents": 0,
|
||||||
|
"degenerate_triangles_dropped": 0,
|
||||||
|
"bounds_min": [
|
||||||
|
-0.858105361,
|
||||||
|
7.834025E-08,
|
||||||
|
-0.389211059
|
||||||
|
],
|
||||||
|
"bounds_max": [
|
||||||
|
0.859303,
|
||||||
|
1.35000026,
|
||||||
|
0.385618329
|
||||||
|
],
|
||||||
|
"clips": [
|
||||||
|
{
|
||||||
|
"name": "ability",
|
||||||
|
"length": 1.20833337,
|
||||||
|
"loop": false,
|
||||||
|
"events": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "attack_a",
|
||||||
|
"length": 1.04166663,
|
||||||
|
"loop": false,
|
||||||
|
"events": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "attack_b",
|
||||||
|
"length": 1.0,
|
||||||
|
"loop": false,
|
||||||
|
"events": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "death",
|
||||||
|
"length": 2.20833325,
|
||||||
|
"loop": false,
|
||||||
|
"events": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hit",
|
||||||
|
"length": 0.5,
|
||||||
|
"loop": false,
|
||||||
|
"events": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idle",
|
||||||
|
"length": 4.0,
|
||||||
|
"loop": true,
|
||||||
|
"events": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "walk",
|
||||||
|
"length": 2.79166675,
|
||||||
|
"loop": true,
|
||||||
|
"events": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "quellgeflecht",
|
"id": "quellgeflecht",
|
||||||
"kind": "skinned",
|
"kind": "skinned",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 1884, "fps": 94.1, "frame_ms_avg": 10.63, "frame_ms_median": 3.90, "frame_ms_p95": 40.03, "frame_ms_p99": 54.34, "frame_ms_max": 75.40, "frames_over_16_7_ms": 408, "of_them_with_simulation_step": 35, "gc_collections": 21, "simulation_ms_per_frame": 0.096, "views_ms_per_frame": 0.227, "ui_ms_per_frame": 0.089, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.96 / median 2.65 / p95 4.59 ms, render thread avg 1.80 / median 1.77 / p95 2.20 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 7.66 / median 0.10 / p95 36.38 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1102, "fps": 110.2, "frame_ms_avg": 9.07, "frame_ms_median": 3.42, "frame_ms_p95": 37.21, "frame_ms_p99": 46.70, "frame_ms_max": 60.00, "frames_over_16_7_ms": 201, "of_them_with_simulation_step": 19, "gc_collections": 9, "simulation_ms_per_frame": 0.056, "views_ms_per_frame": 0.189, "ui_ms_per_frame": 0.069, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.20 / median 2.10 / p95 3.19 ms, render thread avg 1.28 / median 1.26 / p95 1.52 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.91 / median 0.62 / p95 35.07 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 1825, "fps": 91.2, "frame_ms_avg": 10.97, "frame_ms_median": 4.30, "frame_ms_p95": 37.66, "frame_ms_p99": 54.32, "frame_ms_max": 90.51, "frames_over_16_7_ms": 441, "of_them_with_simulation_step": 42, "gc_collections": 21, "simulation_ms_per_frame": 0.110, "views_ms_per_frame": 0.245, "ui_ms_per_frame": 0.094, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 3.26 / median 2.84 / p95 5.24 ms, render thread avg 1.83 / median 1.81 / p95 2.20 ms, gpu avg 0.03 / median 0.00 / p95 0.00 ms, present wait avg 7.69 / median 0.01 / p95 33.91 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1073, "fps": 107.3, "frame_ms_avg": 9.32, "frame_ms_median": 3.70, "frame_ms_p95": 38.07, "frame_ms_p99": 51.00, "frame_ms_max": 61.31, "frames_over_16_7_ms": 191, "of_them_with_simulation_step": 23, "gc_collections": 9, "simulation_ms_per_frame": 0.058, "views_ms_per_frame": 0.209, "ui_ms_per_frame": 0.078, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.44 / median 2.23 / p95 3.89 ms, render thread avg 1.32 / median 1.31 / p95 1.56 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.92 / median 0.12 / p95 35.70 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 1902, "fps": 95.0, "frame_ms_avg": 10.52, "frame_ms_median": 3.69, "frame_ms_p95": 41.10, "frame_ms_p99": 56.01, "frame_ms_max": 92.19, "frames_over_16_7_ms": 409, "of_them_with_simulation_step": 40, "gc_collections": 21, "simulation_ms_per_frame": 0.095, "views_ms_per_frame": 0.215, "ui_ms_per_frame": 0.079, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.78 / median 2.52 / p95 4.01 ms, render thread avg 1.75 / median 1.73 / p95 2.07 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 7.72 / median 0.13 / p95 37.86 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1115, "fps": 111.5, "frame_ms_avg": 8.97, "frame_ms_median": 3.54, "frame_ms_p95": 38.53, "frame_ms_p99": 51.78, "frame_ms_max": 69.20, "frames_over_16_7_ms": 171, "of_them_with_simulation_step": 25, "gc_collections": 9, "simulation_ms_per_frame": 0.057, "views_ms_per_frame": 0.192, "ui_ms_per_frame": 0.067, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.22 / median 2.11 / p95 3.19 ms, render thread avg 1.26 / median 1.24 / p95 1.51 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.79 / median 1.07 / p95 36.51 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 1909, "fps": 95.4, "frame_ms_avg": 10.48, "frame_ms_median": 3.79, "frame_ms_p95": 39.82, "frame_ms_p99": 52.89, "frame_ms_max": 96.95, "frames_over_16_7_ms": 414, "of_them_with_simulation_step": 38, "gc_collections": 21, "simulation_ms_per_frame": 0.092, "views_ms_per_frame": 0.218, "ui_ms_per_frame": 0.079, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.74 / median 2.51 / p95 4.07 ms, render thread avg 1.75 / median 1.73 / p95 2.06 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 7.74 / median 0.19 / p95 37.33 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1104, "fps": 110.3, "frame_ms_avg": 9.06, "frame_ms_median": 3.37, "frame_ms_p95": 38.57, "frame_ms_p99": 51.51, "frame_ms_max": 73.22, "frames_over_16_7_ms": 188, "of_them_with_simulation_step": 14, "gc_collections": 10, "simulation_ms_per_frame": 0.059, "views_ms_per_frame": 0.193, "ui_ms_per_frame": 0.067, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.22 / median 2.08 / p95 3.37 ms, render thread avg 1.28 / median 1.26 / p95 1.51 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.85 / median 0.13 / p95 36.51 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 2066, "fps": 103.2, "frame_ms_avg": 9.69, "frame_ms_median": 3.60, "frame_ms_p95": 35.39, "frame_ms_p99": 46.69, "frame_ms_max": 111.10, "frames_over_16_7_ms": 434, "of_them_with_simulation_step": 44, "gc_collections": 21, "simulation_ms_per_frame": 0.085, "views_ms_per_frame": 0.220, "ui_ms_per_frame": 0.080, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.79 / median 2.55 / p95 4.18 ms, render thread avg 1.76 / median 1.74 / p95 2.07 ms, gpu avg 0.03 / median 0.00 / p95 0.00 ms, present wait avg 6.89 / median 0.13 / p95 32.61 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1183, "fps": 118.2, "frame_ms_avg": 8.46, "frame_ms_median": 3.39, "frame_ms_p95": 31.41, "frame_ms_p99": 40.61, "frame_ms_max": 61.13, "frames_over_16_7_ms": 212, "of_them_with_simulation_step": 22, "gc_collections": 10, "simulation_ms_per_frame": 0.052, "views_ms_per_frame": 0.212, "ui_ms_per_frame": 0.079, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.50 / median 2.27 / p95 4.10 ms, render thread avg 1.33 / median 1.31 / p95 1.60 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 5.93 / median 0.00 / p95 28.87 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 2073, "fps": 103.5, "frame_ms_avg": 9.66, "frame_ms_median": 3.50, "frame_ms_p95": 33.69, "frame_ms_p99": 44.40, "frame_ms_max": 65.71, "frames_over_16_7_ms": 456, "of_them_with_simulation_step": 39, "gc_collections": 22, "simulation_ms_per_frame": 0.087, "views_ms_per_frame": 0.219, "ui_ms_per_frame": 0.078, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.77 / median 2.56 / p95 3.99 ms, render thread avg 1.75 / median 1.73 / p95 2.07 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.88 / median 0.10 / p95 30.96 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1207, "fps": 120.7, "frame_ms_avg": 8.29, "frame_ms_median": 3.47, "frame_ms_p95": 31.71, "frame_ms_p99": 41.91, "frame_ms_max": 57.88, "frames_over_16_7_ms": 207, "of_them_with_simulation_step": 16, "gc_collections": 9, "simulation_ms_per_frame": 0.056, "views_ms_per_frame": 0.216, "ui_ms_per_frame": 0.073, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.51 / median 2.26 / p95 4.16 ms, render thread avg 1.32 / median 1.30 / p95 1.58 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 5.82 / median 0.00 / p95 29.22 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 2095, "fps": 104.7, "frame_ms_avg": 9.55, "frame_ms_median": 3.70, "frame_ms_p95": 36.68, "frame_ms_p99": 48.06, "frame_ms_max": 63.80, "frames_over_16_7_ms": 394, "of_them_with_simulation_step": 34, "gc_collections": 22, "simulation_ms_per_frame": 0.084, "views_ms_per_frame": 0.220, "ui_ms_per_frame": 0.081, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.76 / median 2.58 / p95 3.99 ms, render thread avg 1.75 / median 1.73 / p95 2.08 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.80 / median 0.13 / p95 33.85 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1235, "fps": 123.4, "frame_ms_avg": 8.11, "frame_ms_median": 2.90, "frame_ms_p95": 31.70, "frame_ms_p99": 44.80, "frame_ms_max": 64.40, "frames_over_16_7_ms": 203, "of_them_with_simulation_step": 25, "gc_collections": 9, "simulation_ms_per_frame": 0.049, "views_ms_per_frame": 0.196, "ui_ms_per_frame": 0.067, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.24 / median 2.17 / p95 3.08 ms, render thread avg 1.27 / median 1.26 / p95 1.48 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 5.86 / median 0.00 / p95 29.51 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 2083, "fps": 104.0, "frame_ms_avg": 9.61, "frame_ms_median": 3.51, "frame_ms_p95": 34.73, "frame_ms_p99": 45.15, "frame_ms_max": 70.06, "frames_over_16_7_ms": 445, "of_them_with_simulation_step": 35, "gc_collections": 21, "simulation_ms_per_frame": 0.089, "views_ms_per_frame": 0.224, "ui_ms_per_frame": 0.083, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.83 / median 2.59 / p95 4.30 ms, render thread avg 1.76 / median 1.74 / p95 2.07 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.79 / median 0.06 / p95 31.93 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1187, "fps": 118.7, "frame_ms_avg": 8.43, "frame_ms_median": 3.61, "frame_ms_p95": 32.91, "frame_ms_p99": 42.81, "frame_ms_max": 54.39, "frames_over_16_7_ms": 202, "of_them_with_simulation_step": 23, "gc_collections": 10, "simulation_ms_per_frame": 0.055, "views_ms_per_frame": 0.222, "ui_ms_per_frame": 0.088, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.62 / median 2.29 / p95 5.11 ms, render thread avg 1.32 / median 1.29 / p95 1.62 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 5.81 / median 0.00 / p95 29.62 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 2127, "fps": 106.3, "frame_ms_avg": 9.41, "frame_ms_median": 3.40, "frame_ms_p95": 37.95, "frame_ms_p99": 52.70, "frame_ms_max": 97.25, "frames_over_16_7_ms": 410, "of_them_with_simulation_step": 36, "gc_collections": 22, "simulation_ms_per_frame": 0.082, "views_ms_per_frame": 0.207, "ui_ms_per_frame": 0.077, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.49 / median 2.29 / p95 3.75 ms, render thread avg 1.68 / median 1.65 / p95 2.06 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.92 / median 0.29 / p95 35.59 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1322, "fps": 132.2, "frame_ms_avg": 7.56, "frame_ms_median": 3.01, "frame_ms_p95": 31.41, "frame_ms_p99": 38.58, "frame_ms_max": 48.28, "frames_over_16_7_ms": 201, "of_them_with_simulation_step": 13, "gc_collections": 9, "simulation_ms_per_frame": 0.047, "views_ms_per_frame": 0.198, "ui_ms_per_frame": 0.067, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 2.08 / median 1.96 / p95 3.09 ms, render thread avg 1.20 / median 1.18 / p95 1.43 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 5.50 / median 0.18 / p95 28.86 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 2132, "fps": 106.5, "frame_ms_avg": 9.39, "frame_ms_median": 3.41, "frame_ms_p95": 36.53, "frame_ms_p99": 49.22, "frame_ms_max": 74.49, "frames_over_16_7_ms": 406, "of_them_with_simulation_step": 38, "gc_collections": 21, "simulation_ms_per_frame": 0.083, "views_ms_per_frame": 0.210, "ui_ms_per_frame": 0.075, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.51 / median 2.29 / p95 3.77 ms, render thread avg 1.70 / median 1.67 / p95 2.08 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.87 / median 0.31 / p95 33.75 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1337, "fps": 133.6, "frame_ms_avg": 7.48, "frame_ms_median": 3.00, "frame_ms_p95": 31.88, "frame_ms_p99": 40.00, "frame_ms_max": 53.01, "frames_over_16_7_ms": 194, "of_them_with_simulation_step": 15, "gc_collections": 10, "simulation_ms_per_frame": 0.045, "views_ms_per_frame": 0.190, "ui_ms_per_frame": 0.062, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 1.95 / median 1.85 / p95 2.91 ms, render thread avg 1.19 / median 1.17 / p95 1.40 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 5.54 / median 0.71 / p95 29.81 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 2138, "fps": 106.8, "frame_ms_avg": 9.36, "frame_ms_median": 3.31, "frame_ms_p95": 35.77, "frame_ms_p99": 49.61, "frame_ms_max": 63.82, "frames_over_16_7_ms": 427, "of_them_with_simulation_step": 38, "gc_collections": 22, "simulation_ms_per_frame": 0.080, "views_ms_per_frame": 0.206, "ui_ms_per_frame": 0.077, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.45 / median 2.27 / p95 3.60 ms, render thread avg 1.69 / median 1.66 / p95 2.08 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.91 / median 0.26 / p95 33.23 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1339, "fps": 133.9, "frame_ms_avg": 7.47, "frame_ms_median": 3.05, "frame_ms_p95": 31.39, "frame_ms_p99": 41.03, "frame_ms_max": 70.67, "frames_over_16_7_ms": 190, "of_them_with_simulation_step": 11, "gc_collections": 9, "simulation_ms_per_frame": 0.045, "views_ms_per_frame": 0.188, "ui_ms_per_frame": 0.062, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 1.96 / median 1.83 / p95 3.08 ms, render thread avg 1.18 / median 1.16 / p95 1.39 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 5.50 / median 0.28 / p95 29.34 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"vsync": 0,
|
||||||
|
"match": "seed 9 from round 5, army g01 x36, speed 1x, measured after 10 s of combat",
|
||||||
|
// moving units at the start of the first window: g01 35, w04 14, e04 12, w06 11, w02 7, e01 4, e02 4, w08 4, w10 4, g05 2
|
||||||
|
"windows": [
|
||||||
|
{"view": "overview (zoom 64)", "frames": 2123, "fps": 106.1, "frame_ms_avg": 9.43, "frame_ms_median": 3.46, "frame_ms_p95": 36.58, "frame_ms_p99": 51.40, "frame_ms_max": 75.82, "frames_over_16_7_ms": 405, "of_them_with_simulation_step": 33, "gc_collections": 21, "simulation_ms_per_frame": 0.082, "views_ms_per_frame": 0.214, "ui_ms_per_frame": 0.078, "units_alive_max": 97},
|
||||||
|
// timings overview (zoom 64): main thread avg 2.52 / median 2.33 / p95 3.77 ms, render thread avg 1.70 / median 1.66 / p95 2.10 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 6.90 / median 0.27 / p95 34.03 ms
|
||||||
|
{"view": "mid lane close (zoom 22)", "frames": 1337, "fps": 133.7, "frame_ms_avg": 7.48, "frame_ms_median": 3.00, "frame_ms_p95": 31.00, "frame_ms_p99": 40.70, "frame_ms_max": 65.49, "frames_over_16_7_ms": 188, "of_them_with_simulation_step": 11, "gc_collections": 10, "simulation_ms_per_frame": 0.049, "views_ms_per_frame": 0.189, "ui_ms_per_frame": 0.060, "units_alive_max": 44}
|
||||||
|
// timings mid lane close (zoom 22): main thread avg 1.95 / median 1.87 / p95 2.85 ms, render thread avg 1.18 / median 1.17 / p95 1.39 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 5.54 / median 0.54 / p95 29.05 ms
|
||||||
|
]
|
||||||
|
}
|
||||||
11
docs/port/logs/u5.5-lod/player-smoke.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"build": "OSXPlayer player, 6000.3.20f1, release",
|
||||||
|
"device": "Mac17,2; Apple M5; Apple M5",
|
||||||
|
"graphics_api": "Metal",
|
||||||
|
"resolution": "1920x1080",
|
||||||
|
"seconds": 11.7,
|
||||||
|
"passed": ["Startbildschirm sichtbar", "Partie wartet: Spielcontroller und Treiber aus", "vor dem Start kein HUD", "„Allein spielen“ bedienbar", "Offline: Startbildschirm verborgen", "Offline: Spielcontroller und Treiber laufen", "Offline: HUD sichtbar", "Offline: neue Partie, Sitz 1 (Mid)", "Offline: Planung", "Offline: lokale Sitzung", "„Startaufstellung“ bedienbar", "Startaufstellung gekauft (3 Einheiten)", "„Bereit“ bedienbar", "Bereit: Kampf beginnt", "Kampf: Figuren im Feld", "„Menü“ bedienbar", "Verlassen-Dialog mit „Zum Menü“", "Zurück: Startbildschirm sichtbar", "Zurück: HUD verborgen", "Zurück: Spielcontroller und Treiber aus", "Zurück: Sitzung beendet", "Zurück: keine Figuren im Feld", "Zurück: Kamera ruht", "Zurück: „Allein spielen“ bedienbar", "Zweite Partie: Startbildschirm verborgen, HUD sichtbar", "Zweite Partie: neue Partie in der Planung", "SSAO folgt der Einstellung", "Option „Umgebungsverdeckung“ sichtbar", "Option schaltet SSAO um", "Option stellt SSAO zurück"],
|
||||||
|
"failed": [],
|
||||||
|
"photos": ["00-startbildschirm.jpg", "01-planung.jpg", "02-kampf.jpg", "03-verlassen.jpg", "04-zurueck-im-startbildschirm.jpg", "05-zweite-partie.jpg", "06-optionen.jpg"],
|
||||||
|
"result": "PASS"
|
||||||
|
}
|
||||||
11
docs/port/logs/u5.5-lod/scene-frame-rates.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"match": "seed 2, bots, speed 24x",
|
||||||
|
"core_hash": "DCE95C96556F3A1A",
|
||||||
|
"core_steps": 12690,
|
||||||
|
"runs": [
|
||||||
|
{"target": "30 fps", "frames": 816, "seconds": 27.183, "measured_fps": 30.018, "max_steps_per_frame": 17, "steps": 12690, "hash": "DCE95C96556F3A1A", "winner": 1, "same_as_core": true},
|
||||||
|
{"target": "60 fps", "frames": 1626, "seconds": 27.089, "measured_fps": 60.024, "max_steps_per_frame": 11, "steps": 12690, "hash": "DCE95C96556F3A1A", "winner": 1, "same_as_core": true},
|
||||||
|
{"target": "120 fps", "frames": 3224, "seconds": 26.906, "measured_fps": 119.824, "max_steps_per_frame": 7, "steps": 12690, "hash": "DCE95C96556F3A1A", "winner": 1, "same_as_core": true},
|
||||||
|
{"target": "unlimited", "frames": 83299, "seconds": 26.851, "measured_fps": 3102.282, "max_steps_per_frame": 15, "steps": 12690, "hash": "DCE95C96556F3A1A", "winner": 1, "same_as_core": true}
|
||||||
|
]
|
||||||
|
}
|
||||||
16
docs/port/logs/u5.5-lod/vertical-function-test.json
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"runs": [
|
||||||
|
{"label": "match-seed2", "seed": 2, "start_round": 1, "extra_gold": 0, "speed": 6, "winner": 1, "end_note": "Ancient von Blau zerstört.", "steps": 12690, "hash": "DCE95C96556F3A1A", "core_hash": "DCE95C96556F3A1A", "same_as_core": true,
|
||||||
|
"units_alive_max": 84, "heroes_alive_max": 4, "boss_log": ["round 8: won team 1 ", "round 9: deployed team 1 bot"],
|
||||||
|
"rounds": [{"round": 1, "combat_seconds": 44.9, "lost": [], "boss": "none", "end": "cleared"}, {"round": 2, "combat_seconds": 57.1, "lost": [], "boss": "none", "end": "cleared"}, {"round": 3, "combat_seconds": 54.1, "lost": [], "boss": "none", "end": "cleared"}, {"round": 4, "combat_seconds": 62.9, "lost": [], "boss": "none", "end": "cleared"}, {"round": 5, "combat_seconds": 60.7, "lost": [], "boss": "none", "end": "cleared"}, {"round": 6, "combat_seconds": 62.1, "lost": [], "boss": "none", "end": "cleared"}, {"round": 7, "combat_seconds": 66.5, "lost": ["blau_bot_outer"], "boss": "none", "end": "cleared"}, {"round": 8, "combat_seconds": 89.65, "lost": ["rot_top_outer", "rot_top_inner"], "boss": "won", "end": "cleared"}, {"round": 9, "combat_seconds": 136.55, "lost": ["blau_bot_inner", "blau_base_2", "blau_base_1", "blau_ancient"], "boss": "deployed", "end": "core"}],
|
||||||
|
"events": ["round 7: blau_bot_outer destroyed", "round 8: rot_top_outer destroyed", "round 8: rot_top_inner destroyed", "round 8: grotto boss won", "round 9: blau_bot_inner destroyed", "round 9: blau_base_2 destroyed", "round 9: blau_base_1 destroyed", "round 9: blau_ancient destroyed", "round 9: grotto boss deployed"],
|
||||||
|
"shots": ["01-runde1-aufmarsch", "02-runde1-mid-kampf", "03-turm-faellt", "04-turm-ruine", "05-grotte-bosskampf", "06-held-kaempft", "07-boss-auf-der-lane", "08-ancient-faellt", "09-ancient-ruine", "10-ende-uebersicht"],
|
||||||
|
"performance": null},
|
||||||
|
{"label": "match-seed9-round21", "seed": 9, "start_round": 21, "extra_gold": 4000, "speed": 6, "winner": 0, "end_note": "Ancient von Rot zerstört.", "steps": 4195, "hash": "7B8E43AEFC0D60C5", "core_hash": "7B8E43AEFC0D60C5", "same_as_core": true,
|
||||||
|
"units_alive_max": 125, "heroes_alive_max": 6, "boss_log": [],
|
||||||
|
"rounds": [{"round": 21, "combat_seconds": 121.8, "lost": ["rot_mid_outer", "rot_top_outer", "rot_mid_inner"], "boss": "none", "end": "cleared"}, {"round": 22, "combat_seconds": 87.95, "lost": ["rot_top_inner", "rot_base_1", "blau_bot_outer", "rot_base_2", "rot_ancient"], "boss": "none", "end": "core"}],
|
||||||
|
"events": ["round 21: rot_mid_outer destroyed", "round 21: rot_top_outer destroyed", "round 21: rot_mid_inner destroyed", "round 22: rot_top_inner destroyed", "round 22: rot_base_1 destroyed", "round 22: blau_bot_outer destroyed", "round 22: rot_base_2 destroyed", "round 22: rot_ancient destroyed"],
|
||||||
|
"shots": ["11-welle21-uebersicht", "12-welle21-kampf", "13-ancient-rot-faellt", "14-welle-ende"],
|
||||||
|
"performance": {"window": "20 s real time at 1x speed, unlimited frame rate, round 21", "frames": 56103, "fps": 2805.12, "frame_ms_avg": 0.356, "frame_ms_p95": 0.413, "simulation_ms_per_frame": 0.003, "views_ms_per_frame": 0.124, "units_alive_max": 116}}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
docs/port/screenshots/u5.5-lod/01-runde1-aufmarsch.jpg
Normal file
|
After Width: | Height: | Size: 596 KiB |
BIN
docs/port/screenshots/u5.5-lod/02-runde1-mid-kampf.jpg
Normal file
|
After Width: | Height: | Size: 610 KiB |
BIN
docs/port/screenshots/u5.5-lod/03-turm-faellt.jpg
Normal file
|
After Width: | Height: | Size: 537 KiB |
BIN
docs/port/screenshots/u5.5-lod/04-turm-ruine.jpg
Normal file
|
After Width: | Height: | Size: 528 KiB |
BIN
docs/port/screenshots/u5.5-lod/05-grotte-bosskampf.jpg
Normal file
|
After Width: | Height: | Size: 609 KiB |
BIN
docs/port/screenshots/u5.5-lod/06-held-kaempft.jpg
Normal file
|
After Width: | Height: | Size: 624 KiB |
BIN
docs/port/screenshots/u5.5-lod/07-boss-auf-der-lane.jpg
Normal file
|
After Width: | Height: | Size: 576 KiB |
BIN
docs/port/screenshots/u5.5-lod/08-ancient-faellt.jpg
Normal file
|
After Width: | Height: | Size: 623 KiB |
BIN
docs/port/screenshots/u5.5-lod/09-ancient-ruine.jpg
Normal file
|
After Width: | Height: | Size: 623 KiB |
BIN
docs/port/screenshots/u5.5-lod/10-ende-uebersicht.jpg
Normal file
|
After Width: | Height: | Size: 434 KiB |
BIN
docs/port/screenshots/u5.5-lod/11-welle21-uebersicht.jpg
Normal file
|
After Width: | Height: | Size: 592 KiB |
BIN
docs/port/screenshots/u5.5-lod/12-welle21-kampf.jpg
Normal file
|
After Width: | Height: | Size: 648 KiB |
BIN
docs/port/screenshots/u5.5-lod/13-ancient-rot-faellt.jpg
Normal file
|
After Width: | Height: | Size: 601 KiB |
BIN
docs/port/screenshots/u5.5-lod/14-welle-ende.jpg
Normal file
|
After Width: | Height: | Size: 580 KiB |
BIN
docs/port/screenshots/u5.5-lod/figur/kohlenbeisser-attack_a.jpg
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
docs/port/screenshots/u5.5-lod/figur/kohlenbeisser.jpg
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
docs/port/screenshots/u5.5-lod/spiel/01-aufstellung-nah.jpg
Normal file
|
After Width: | Height: | Size: 715 KiB |
BIN
docs/port/screenshots/u5.5-lod/spiel/02-portraet.jpg
Normal file
|
After Width: | Height: | Size: 714 KiB |
BIN
docs/port/screenshots/u5.5-lod/spiel/03-kampf-nah.jpg
Normal file
|
After Width: | Height: | Size: 638 KiB |
BIN
docs/port/screenshots/u5.5-lod/spiel/04-kampf-lane.jpg
Normal file
|
After Width: | Height: | Size: 643 KiB |
|
|
@ -1605,7 +1605,7 @@
|
||||||
},
|
},
|
||||||
"replaces": "g01",
|
"replaces": "g01",
|
||||||
"expect": {
|
"expect": {
|
||||||
"triangles": 20714,
|
"triangles": 25712,
|
||||||
"bones": 25,
|
"bones": 25,
|
||||||
"clips": [
|
"clips": [
|
||||||
"idle",
|
"idle",
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,62 @@ def textures(material, prefix, rule, colours):
|
||||||
return {'glow_share': round(float(mask.mean()), 4), 'palette_gains': gains, 'size': list(found['albedo'].size)}
|
return {'glow_share': round(float(mask.mean()), 4), 'palette_gains': gains, 'size': list(found['albedo'].size)}
|
||||||
|
|
||||||
|
|
||||||
|
def lane_lod(body, rule):
|
||||||
|
"""The lane-distance copy (LOD1): the seam copies welded (Meshy splits the mesh along its UV
|
||||||
|
seams), decimated to the target triangle count, sharp edges from the angle instead of Meshy's
|
||||||
|
split normals. Decimation keeps UVs, material and vertex groups (the skin weights).
|
||||||
|
The meshes are named <body>_LOD0 / _LOD1, Unity builds the LODGroup from the names."""
|
||||||
|
import bmesh
|
||||||
|
lod = body.copy()
|
||||||
|
lod.data = body.data.copy()
|
||||||
|
body.users_collection[0].objects.link(lod)
|
||||||
|
mesh = lod.data
|
||||||
|
if mesh.has_custom_normals:
|
||||||
|
bpy.context.view_layer.objects.active = lod
|
||||||
|
with bpy.context.temp_override(object=lod, active_object=lod, selected_objects=[lod]):
|
||||||
|
bpy.ops.mesh.customdata_custom_splitnormals_clear()
|
||||||
|
bm = bmesh.new()
|
||||||
|
bm.from_mesh(mesh)
|
||||||
|
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=rule.get('weld', 1e-4))
|
||||||
|
bm.to_mesh(mesh)
|
||||||
|
bm.free()
|
||||||
|
before = sum(len(poly.vertices) - 2 for poly in mesh.polygons)
|
||||||
|
decimate = lod.modifiers.new('LaneLod', 'DECIMATE')
|
||||||
|
decimate.decimate_type = 'COLLAPSE'
|
||||||
|
decimate.ratio = min(1.0, rule['triangles'] / max(before, 1))
|
||||||
|
decimate.use_collapse_triangulate = True
|
||||||
|
while lod.modifiers[0] != decimate:
|
||||||
|
lod.modifiers.move(lod.modifiers.find(decimate.name), 0)
|
||||||
|
with bpy.context.temp_override(object=lod, active_object=lod):
|
||||||
|
bpy.ops.object.modifier_apply(modifier=decimate.name)
|
||||||
|
# Collapsing can leave zero-area triangles; the FBX round trip drops them, so they go here ...
|
||||||
|
bm = bmesh.new()
|
||||||
|
bm.from_mesh(mesh)
|
||||||
|
bmesh.ops.dissolve_degenerate(bm, edges=bm.edges, dist=1e-6)
|
||||||
|
bmesh.ops.triangulate(bm, faces=[f for f in bm.faces if len(f.verts) > 3])
|
||||||
|
# ... and faces folded onto the same three vertices (the FBX import keeps only one).
|
||||||
|
seen = set()
|
||||||
|
twins = []
|
||||||
|
for face in bm.faces:
|
||||||
|
key = tuple(sorted(v.index for v in face.verts))
|
||||||
|
if key in seen:
|
||||||
|
twins.append(face)
|
||||||
|
seen.add(key)
|
||||||
|
bmesh.ops.delete(bm, geom=twins, context='FACES_ONLY')
|
||||||
|
bm.to_mesh(mesh)
|
||||||
|
bm.free()
|
||||||
|
for poly in mesh.polygons:
|
||||||
|
poly.use_smooth = True
|
||||||
|
mesh.set_sharp_from_angle(angle=math.radians(rule.get('sharp_degrees', 50)))
|
||||||
|
name = body.name
|
||||||
|
body.name = body.data.name = name + '_LOD0'
|
||||||
|
lod.name = lod.data.name = name + '_LOD1'
|
||||||
|
after = sum(len(poly.vertices) - 2 for poly in mesh.polygons)
|
||||||
|
return {'lod0_triangles': sum(len(poly.vertices) - 2 for poly in body.data.polygons),
|
||||||
|
'lod1_triangles': after, 'lod1_vertices': len(mesh.vertices), 'welded_triangles': before,
|
||||||
|
'lod0_screen': rule.get('lod0_screen', 0.1)}
|
||||||
|
|
||||||
|
|
||||||
def build(figure_path, source_root, unity_root):
|
def build(figure_path, source_root, unity_root):
|
||||||
figure = json.loads(figure_path.read_text())
|
figure = json.loads(figure_path.read_text())
|
||||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||||
|
|
@ -318,8 +374,9 @@ def build(figure_path, source_root, unity_root):
|
||||||
tree.nodes.remove(node)
|
tree.nodes.remove(node)
|
||||||
for image in list(bpy.data.images):
|
for image in list(bpy.data.images):
|
||||||
bpy.data.images.remove(image)
|
bpy.data.images.remove(image)
|
||||||
|
lod = lane_lod(body, figure['lod']) if 'lod' in figure else None
|
||||||
scene.frame_set(0)
|
scene.frame_set(0)
|
||||||
return {'clips': clips, 'textures': maps, 'unit': unit}
|
return {'clips': clips, 'textures': maps, 'unit': unit, 'lod': lod}
|
||||||
|
|
||||||
|
|
||||||
figure_file, source_dir, unity_dir, save_to = options()
|
figure_file, source_dir, unity_dir, save_to = options()
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
"textures": "Assets/Luneraria/Art/Textures/ai-kohlenbeisser",
|
"textures": "Assets/Luneraria/Art/Textures/ai-kohlenbeisser",
|
||||||
"root_bone": "Root",
|
"root_bone": "Root",
|
||||||
"glow": {"hue": [0, 42], "saturation": 0.6, "value": 0.5, "metal_below": 0.5},
|
"glow": {"hue": [0, 42], "saturation": 0.6, "value": 0.5, "metal_below": 0.5},
|
||||||
|
"lod": {"triangles": 5000, "sharp_degrees": 50, "lod0_screen": 0.2},
|
||||||
"palette": {"rock": {"color": "41434b", "strength": 0.8}, "metal": {"color": "c99645", "strength": 1.0}},
|
"palette": {"rock": {"color": "41434b", "strength": 0.8}, "metal": {"color": "c99645", "strength": 1.0}},
|
||||||
"clips": {
|
"clips": {
|
||||||
"idle": {"source": "Idle", "loop": true},
|
"idle": {"source": "Idle", "loop": true},
|
||||||
|
|
|
||||||