Draw props whose materials a map borrows from common_mp

A map zone streams the materials it shares with common_mp as ",name"
references: stubs with no textures and no technique set. Since
capture_material refuses a material without a technique set, the slot of
such a reference was never bound and every model surface on it was
dropped: 97 of the 14551 map model surfaces on mp_terminal and 28 of the
14125 on mp_favela, among them a surface of the wall fan cs_wallfan1 and
one of the air conditioner com_ex_airconditioner.

When the capture refuses a reference, the slot is now bound to the real
material of the same name and namespace, which the common pool already
holds. A reference with no real counterpart stays unbound as before.

",mc/shadowcaster" references bind now too, so scene_lit_pass_material
skips shadow-only materials for script models and dyn ents, as the static
model path already does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
JohnM
2026-10-10 00:11:53 +08:00
parent 91217cd0ac
commit 71e6e18c1c
2 changed files with 22 additions and 1 deletions
+19 -1
View File
@@ -937,6 +937,21 @@ impl MaterialCatalog {
)
}
fn reference_material_index(&self, s: &ZoneStream<'_>) -> Option<usize> {
let name = s
.latest_material()?
.name
.and_then(|name| s.cstr(name).ok())
.map(AssetRef::decode)?;
if !name.is_reference() {
return None;
}
let namespace = self.capture_ns?;
self.materials
.iter()
.position(|m| m.namespace == namespace && m.name.is_real() && m.name.same_name(&name))
}
fn capture_material(&mut self, s: &ZoneStream<'_>) -> Option<usize> {
let geometry = s.latest_material()?;
let name = geometry
@@ -1299,7 +1314,10 @@ impl AssetLinkSink for MaterialCatalog {
}
AssetType::Material => {
let header = s.latest_material().and_then(|g| g.header);
let Some(index) = self.capture_material(s) else {
let Some(index) = self
.capture_material(s)
.or_else(|| self.reference_material_index(s))
else {
self.capture_gaps += 1;
return Ok(());
};
@@ -111,6 +111,9 @@ pub fn scene_lit_pass_material(
authored: assets::MaterialIndex,
) -> Option<SmodelPassMaterial> {
let world_material = tess.catalog().derived(authored)?;
if world_material.shadow_only {
return None;
}
let ordinal = tess
.catalog()
.parts()