Wreck scorch quad: kill the black-rectangle tint + cross-library textures (issue #3)
The opaque BLACK rectangle under a destroyed truck was basev:bvx9_mtl (the MECHMD wreck's 4-vtx scorch base): the material authors NO diffuse, ambient (0,0,0), texture bexp9_tex (MAP 'bexp' slice 8, BEXP.BSL) + ramp cdusty. collectMaterials' AMBIENT fallback took the all-zero ambient as a REAL colour (hasDiffuse=true, black) and tinted the whole quad black regardless of its texture. An all-zero ambient means UNSET, not 'tint black' (a black tint renders geometry invisible -- never authored intent): the fallback now requires r+g+b > 0.001. Pixel-verified (BT_SHOT ram run): the scorch base draws as the authored charred burn patch under the wreck debris. Also: cross-library TEXTURE registry (globalTexMaps, BT_TEX_XLIB=0 disables) mirroring the existing globalRamps -- material libs reference textures DEFINED in other libs (bexp9_tex is defined in BTARENA/BTFX, not BASEV.BMF); a per-file texMaps miss left such batches untextured. Same first-wins sweep of the indexed BMFs on first miss. Regression scope: only materials authoring a zero ambient AND no diffuse change (they now ramp/texture instead of black); cross-lib refs that previously resolved keep their same-file definitions (checked first). Awaiting human verification in a live session (issue #3 stays open). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
83385b0661
commit
557e9fd243
@@ -421,6 +421,36 @@ struct MaterialResolver {
|
||||
return reg;
|
||||
}
|
||||
|
||||
// CROSS-LIBRARY TEXTURE REGISTRY (issue #3, the black scorch quad): material
|
||||
// libs also reference TEXTURES defined in OTHER libs -- MECHMD.bgf's scorch
|
||||
// base uses basev:bvx9_mtl whose texture `bexp9_tex` is defined in the FX
|
||||
// libs (image in BEXP.BSL), not in BASEV.BMF. A per-file texMaps lookup
|
||||
// left the quad untextured, drawn with its zero ambient = an opaque BLACK
|
||||
// rectangle. Same shape as the ramp registry above: on first cross-file
|
||||
// miss, sweep the indexed BMFs once and cache every TEXTURE definition
|
||||
// (first stem in priority order wins; same-file defs are preferred before
|
||||
// this registry is hit). BT_TEX_XLIB=0 disables.
|
||||
static const std::map<std::string, TexRef>& globalTexMaps() {
|
||||
static std::map<std::string, TexRef> reg;
|
||||
static bool built = false;
|
||||
if (!built) {
|
||||
built = true;
|
||||
const char* v = getenv("BT_TEX_XLIB");
|
||||
if (v == nullptr || v[0] != '0') {
|
||||
for (const auto& kv : bmfIndex()) {
|
||||
std::vector<uint8_t> buf = readFileBytes(kv.second);
|
||||
if (buf.size() <= 8 || std::memcmp(buf.data(), "DIV-BIZ2", 8) != 0) continue;
|
||||
std::vector<Chunk> roots;
|
||||
if (!parseRange(buf.data() + 8, buf.data() + buf.size(), roots)) continue;
|
||||
std::map<std::string, TexRef> maps;
|
||||
collectTextureMaps(roots, maps);
|
||||
for (const auto& m : maps) reg.insert(m); // first wins
|
||||
}
|
||||
}
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
static void collectMaterials(const std::vector<Chunk>& cs,
|
||||
const std::map<std::string, TexRef>& texMaps,
|
||||
const std::map<std::string, std::array<float,6> >& ramps,
|
||||
@@ -438,7 +468,13 @@ struct MaterialResolver {
|
||||
info.color = packColor(rdF32(ch.data), rdF32(ch.data + 4), rdF32(ch.data + 8));
|
||||
haveColor = true;
|
||||
info.hasDiffuse = true;
|
||||
} else if (ch.id == TAG_AMBIENT && ch.len >= 12 && !haveColor) {
|
||||
} else if (ch.id == TAG_AMBIENT && ch.len >= 12 && !haveColor
|
||||
&& (rdF32(ch.data) + rdF32(ch.data + 4) + rdF32(ch.data + 8)) > 0.001f) {
|
||||
// AMBIENT fallback only when it carries a real colour: an
|
||||
// all-zero ambient means "unset", not "tint black" -- e.g.
|
||||
// basev:bvx9_mtl (the wreck scorch quad, issue #3) authors
|
||||
// ambient (0,0,0) + texture + ramp; the black fallback
|
||||
// painted the whole quad as an opaque BLACK rectangle.
|
||||
info.color = packColor(rdF32(ch.data), rdF32(ch.data + 4), rdF32(ch.data + 8));
|
||||
haveColor = true;
|
||||
info.hasDiffuse = true;
|
||||
@@ -467,16 +503,25 @@ struct MaterialResolver {
|
||||
}
|
||||
}
|
||||
if (!name.empty() && (haveColor || !texName.empty() || info.hasRamp)) {
|
||||
const TexRef* ref = nullptr;
|
||||
auto tm = texMaps.find(texName);
|
||||
if (tm != texMaps.end()) {
|
||||
if (tm != texMaps.end()) ref = &tm->second;
|
||||
else if (!texName.empty()) {
|
||||
// cross-library texture reference (see globalTexMaps):
|
||||
// e.g. basev:bvx9_mtl -> bexp9_tex (defined in the FX libs)
|
||||
const auto& reg = globalTexMaps();
|
||||
auto gt = reg.find(texName);
|
||||
if (gt != reg.end()) ref = >->second;
|
||||
}
|
||||
if (ref != nullptr) {
|
||||
const auto& imgs = imageIndex();
|
||||
auto f = imgs.find(stemLower(tm->second.map));
|
||||
auto f = imgs.find(stemLower(ref->map));
|
||||
if (f != imgs.end()) {
|
||||
info.texPath = f->second;
|
||||
info.texChannel = tm->second.channel;
|
||||
info.texScroll = tm->second.scroll;
|
||||
info.texScrollU = tm->second.scrollU;
|
||||
info.texScrollV = tm->second.scrollV;
|
||||
info.texChannel = ref->channel;
|
||||
info.texScroll = ref->scroll;
|
||||
info.texScrollU = ref->scrollU;
|
||||
info.texScrollV = ref->scrollV;
|
||||
}
|
||||
}
|
||||
out[name] = info;
|
||||
|
||||
Reference in New Issue
Block a user