Rock Gen 2.17.0: Erz-Maske invertiert - Nuggets laufen auf A = 0 zu
Entscheidung der Spielseite: die A-Semantik bleibt eingefroren (1.0 = kein Erz),
der Master loest es ueber
Erz = (1 - A) * ErzMenge
mit ErzMenge als MI-Regler, Standard 0. Normale Stein-MIs ignorieren den Kanal
damit vollstaendig, nur die Erz-MIs drehen ihn auf. Kein Re-Export des
25er-Sets noetig, keine Fallunterscheidung im Addon.
Dafuer musste die Maske umgedreht werden: bisher lag das Nugget-ZENTRUM auf
A = 1.0 - also auf demselben Wert wie "kein Erz". Unter der Master-Formel waere
das Erz damit unsichtbar gewesen und der ganze RESTLICHE Stein haette als Erz
gegolten. Jetzt laufen die Nuggets auf A = 0 zu.
Gemessen: ohne Erz A 1.00..1.00 und (1-A) max 0.000 - ein normaler Stein zeigt
im Master garantiert nichts. Mit Erz erreicht (1-A) 1.00, Abdeckung unveraendert
4/9/15 % bei Anteil 0.08/0.18/0.35. Die Erzstellen sitzen an denselben Punkten
wie vorher, nur andersherum kodiert.
Die Tests pruefen jetzt direkt gegen die Master-Formel statt gegen den Rohwert -
am Rohkanal ist die Richtung zu leicht zu verwechseln. Panel zeigt bei aktivem
Erz-Bake "A=Erz (0=Erz)" plus den Hinweis auf die Formel, damit das niemand
versehentlich zurueckdreht.
Nugget-Groesse bleibt wie entschieden ABSOLUT (Radius in Metern).
ACHTUNG: Erz-Assets, die mit 2.15/2.16 exportiert wurden, tragen die alte
Richtung und muessen neu exportiert werden. Steine ohne Erz-Bake sind nicht
betroffen - deren A war und ist durchgehend 1.0.
17 Tests bestehen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+28
-13
@@ -3,6 +3,10 @@
|
||||
Kernaussagen, die hier festgenagelt werden:
|
||||
* EIN neutrales Set - die A-Maske sagt nur WO Erz sitzt, nicht welches.
|
||||
* Ohne Erz bleibt A auf 1.0 (Layout v2, wie das bestehende 25er-Set).
|
||||
* A wird INVERTIERT gebacken: 1.0 = kein Erz, 0.0 = Erz. Der Master rechnet
|
||||
`(1 - A) * ErzMenge` mit ErzMenge als MI-Regler (Standard 0) - normale
|
||||
Stein-MIs ignorieren den Kanal damit komplett. Geprueft wird deshalb direkt
|
||||
gegen diese Formel und nicht gegen den Rohwert.
|
||||
* Die Maske ueberlebt den FBX-Roundtrip.
|
||||
* Die Aufloesung der Maske haengt an der Vertex-Dichte - deshalb erzeugt das
|
||||
Erz-Set dicht. Bei ~150 Verts waren die Nugget-Zentren jeder dritte Vertex
|
||||
@@ -49,28 +53,37 @@ def einer(**kw):
|
||||
return ob, a, tris
|
||||
|
||||
|
||||
# --- 1) Ohne Erz bleibt A auf 1.0 ----------------------------------------
|
||||
def erz_aus_a(a):
|
||||
"""Was der Master sieht: (1 - A). 0 = kein Erz, 1 = volles Erz."""
|
||||
return [1.0 - x for x in a]
|
||||
|
||||
|
||||
# --- 1) Ohne Erz sieht der Master NICHTS ---------------------------------
|
||||
_, a, _ = einer(bake_ore=False, subsurf_levels=4)
|
||||
if min(a) < 0.999:
|
||||
fails.append("Ohne Erz ist A nicht 1.0 (min %.3f) - das bricht das "
|
||||
"eingefrorene Layout v2 und das bestehende 25er-Set" % min(a))
|
||||
if max(erz_aus_a(a)) > 0.001:
|
||||
fails.append("Ohne Erz liefert (1-A) bis %.3f - ein normaler Stein wuerde "
|
||||
"im Master Erz zeigen" % max(erz_aus_a(a)))
|
||||
|
||||
# --- 2) Mit Erz: Maske vorhanden, Anteil steigt monoton -------------------
|
||||
print("%-24s %7s %7s %9s %7s" % ("Variante", "A min", "A max", "A>0.5", "Tris"))
|
||||
print("%-24s %7s %7s %9s %7s" % ("Variante", "A min", "A max", "Erz-Anteil", "Tris"))
|
||||
anteile = []
|
||||
for amt in (0.08, 0.18, 0.35):
|
||||
ob, a, tris = einer(bake_ore=True, ore_amount=amt, ore_nugget_size=0.10,
|
||||
subsurf_levels=5, decimate_ratio_1=0.40,
|
||||
decimate_ratio_2=0.80)
|
||||
anteil = sum(1 for x in a if x > 0.5) / len(a)
|
||||
erz = erz_aus_a(a)
|
||||
anteil = sum(1 for x in erz if x > 0.5) / len(erz)
|
||||
anteile.append(anteil)
|
||||
print("%-24s %7.2f %7.2f %8.0f%% %7d"
|
||||
% ("Erz-Anteil %.2f" % amt, min(a), max(a), 100 * anteil, tris))
|
||||
if max(a) < 0.9:
|
||||
fails.append("Erz-Anteil %.2f: A erreicht nur %.2f - keine Nuggets"
|
||||
% (amt, max(a)))
|
||||
if min(a) > 0.01:
|
||||
fails.append("Erz-Anteil %.2f: A faellt nie auf 0 - der ganze Stein "
|
||||
if max(erz) < 0.9:
|
||||
fails.append("Erz-Anteil %.2f: (1-A) erreicht nur %.2f - die Nuggets "
|
||||
"laufen nicht auf A=0 zu" % (amt, max(erz)))
|
||||
if min(erz) > 0.01:
|
||||
fails.append("Erz-Anteil %.2f: (1-A) faellt nie auf 0 - der ganze Stein "
|
||||
"waere Erz" % amt)
|
||||
if not (anteile[0] < anteile[1] < anteile[2]):
|
||||
fails.append("Erz-Anteil wirkt nicht monoton: %s"
|
||||
@@ -124,8 +137,9 @@ for ob in bpy.context.scene.objects:
|
||||
fails.append("%s hat nur %d Verts - zu grob fuer eine Nugget-Maske"
|
||||
% (ob.name, len(ob.data.vertices)))
|
||||
a = [c.color[3] for c in ob.data.color_attributes["Cavity"].data]
|
||||
if max(a) < 0.9:
|
||||
fails.append("%s traegt keine Erz-Maske (A max %.2f)" % (ob.name, max(a)))
|
||||
if max(erz_aus_a(a)) < 0.9:
|
||||
fails.append("%s traegt keine Erz-Maske ((1-A) max %.2f)"
|
||||
% (ob.name, max(erz_aus_a(a))))
|
||||
|
||||
s_hoch = max(v for k, v in hoehen.items() if "_S_" in k)
|
||||
m_hoch = min(v for k, v in hoehen.items() if "_M_" in k)
|
||||
@@ -150,12 +164,13 @@ else:
|
||||
ob = [o for o in bpy.context.scene.objects
|
||||
if o.type == 'MESH' and not o.name.startswith("UCX_")][0]
|
||||
a = [c.color[3] for c in ob.data.color_attributes[0].data]
|
||||
anteil = sum(1 for x in a if x > 0.5) / len(a)
|
||||
erz = erz_aus_a(a)
|
||||
anteil = sum(1 for x in erz if x > 0.5) / len(erz)
|
||||
print("Nach FBX (%s): A %.2f..%.2f, Erz auf %.0f%%"
|
||||
% (dateien[0], min(a), max(a), 100 * anteil))
|
||||
if max(a) < 0.9 or min(a) > 0.01:
|
||||
if max(erz) < 0.9 or min(erz) > 0.01:
|
||||
fails.append("Erz-Maske ueberlebt den FBX-Roundtrip nicht "
|
||||
"(A %.2f..%.2f)" % (min(a), max(a)))
|
||||
"((1-A) %.2f..%.2f)" % (min(erz), max(erz)))
|
||||
|
||||
print("")
|
||||
if fails:
|
||||
|
||||
Reference in New Issue
Block a user