MONKEY (fix-wind): one grass bend span per model; warm the clutter UV_1 layout
Review W4: the bend height was normalised per submesh, so a trunk + canopy detail doodad tore apart at the seam; the span is now taken over all of the model's submeshes. Review W5: clutter meshes carry UV_1 (VERTEX_UVS_B), so the six clutter pipelines are also warmed on the POS+NORMAL+UV0+UV1+COLOR quad. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
cf7b401599
commit
bc7dc6509b
@@ -278,6 +278,7 @@ pub(super) fn spawn_menagerie(
|
||||
// doodad's trunk batch is Opaque, its canopy Blend, and the builder's untextured fallback is
|
||||
// Opaque + back-cull with the fade still armed — each its own key (0958's sweep; 0938 warmed
|
||||
// Mask only).
|
||||
let mut clutter_mats: Vec<Handle<WowModelMaterial>> = Vec::new();
|
||||
for two_sided in [false, true] {
|
||||
for blend in [ModelBlend::Opaque, ModelBlend::AlphaTest, ModelBlend::Blend] {
|
||||
let plain = model_material(
|
||||
@@ -316,6 +317,8 @@ pub(super) fn spawn_menagerie(
|
||||
let mut m = m.clone();
|
||||
m.extension.clutter_fade = Vec4::new(52.5, 70.0, 0.0, 1.0);
|
||||
let clutter = materials.add(m);
|
||||
// MONKEY (fix-wind): also on the clutter mesh layout (UV_1 = wind height/phase).
|
||||
clutter_mats.push(clutter.clone());
|
||||
mats.push(clutter);
|
||||
}
|
||||
}
|
||||
@@ -496,6 +499,19 @@ pub(super) fn spawn_menagerie(
|
||||
let posuv = meshes.add(warm_pos_uv_mesh());
|
||||
let liquid_mesh = meshes.add(warm_liquid_mesh(false));
|
||||
let liquid_color_mesh = meshes.add(warm_liquid_mesh(true));
|
||||
// MONKEY (fix-wind): clutter meshes carry POS + NORMAL + UV_0 + UV_1 (wind) + COLOR, a layout
|
||||
// (and `VERTEX_UVS_B`) the model quads lack; the liquid colour quad has exactly that set.
|
||||
for mat in &clutter_mats {
|
||||
spawn_lane_rig(
|
||||
commands,
|
||||
cam,
|
||||
None,
|
||||
&liquid_color_mesh,
|
||||
None,
|
||||
mat.clone(),
|
||||
&mut count,
|
||||
);
|
||||
}
|
||||
// Celestial discs + glares (`sun::setup` quads: position+normal+UV).
|
||||
for mat in lane_handles(&mut lanes.celestial) {
|
||||
spawn_lane_rig(
|
||||
|
||||
@@ -322,17 +322,19 @@ fn build_chunk_clutter(
|
||||
if subs.is_empty() {
|
||||
continue;
|
||||
}
|
||||
// MONKEY (wind): source M2 Z is up. Normalize the actual tuft geometry rather than
|
||||
// trusting texture V (WXL's 3.3.5 detail doodads use inverse V, but vanilla assets are
|
||||
// not guaranteed to). UV_1 stays free here and carries height + per-tuft phase.
|
||||
// MONKEY (fix-wind): one span over ALL of the model's submeshes, so a trunk + canopy pair
|
||||
// bends as one body instead of tearing apart at the seam.
|
||||
let (min_z, max_z) = subs
|
||||
.iter()
|
||||
.flat_map(|sub| sub.positions.iter())
|
||||
.fold((f32::INFINITY, f32::NEG_INFINITY), |(lo, hi), p| {
|
||||
(lo.min(p[2]), hi.max(p[2]))
|
||||
});
|
||||
let height_span = (max_z - min_z).max(1.0e-4);
|
||||
for sub in subs.iter() {
|
||||
// MONKEY (wind): source M2 Z is up. Normalize the actual tuft geometry rather than
|
||||
// trusting texture V (WXL's 3.3.5 detail doodads use inverse V, but vanilla assets are
|
||||
// not guaranteed to). UV_1 stays free here and carries height + per-tuft phase.
|
||||
let (min_z, max_z) = sub
|
||||
.positions
|
||||
.iter()
|
||||
.fold((f32::INFINITY, f32::NEG_INFINITY), |(lo, hi), p| {
|
||||
(lo.min(p[2]), hi.max(p[2]))
|
||||
});
|
||||
let height_span = (max_z - min_z).max(1.0e-4);
|
||||
let vcount = sub.positions.len() * placements.len();
|
||||
let mut positions = Vec::with_capacity(vcount);
|
||||
let mut uvs = Vec::with_capacity(vcount);
|
||||
|
||||
Reference in New Issue
Block a user