Divide out player scale from ConcealmentMeter baked mesh
SkinnedMeshRenderer.BakeMesh(mesh) bakes the renderer's world scale into the vertices. SkinnedColliderBaker already accounts for this and divides it back out, but ConcealmentMeter did not: it lifted the already-scaled verts to world via localToWorldMatrix (scale again), yielding scale-squared voxel positions. This threw off the embedded broadphase box, the EmbeddedPercent computation (which now drives the X-ray reveal) and the debug gizmos whenever PlayerScaler != 1. Rescale the baked mesh to unit scale right after baking (no-op at scale 1), matching the SkinnedColliderBaker convention documented in PlayerScaler, so world = localToWorldMatrix holds on unit geometry. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
2f38cf0e32
commit
8603b0d884
1 file changed
+34
-2
@@ -10,8 +10,10 @@ using UnityEngine;
|
||||
/// <see cref="VisiblePercent"/> its complement.
|
||||
///
|
||||
/// Pipeline:
|
||||
/// 1. <see cref="SkinnedMeshRenderer.BakeMesh(Mesh)"/> -> mesh in the renderer's LOCAL space
|
||||
/// (same convention MeshPainter uses for its collider; world = transform.localToWorldMatrix).
|
||||
/// 1. <see cref="SkinnedMeshRenderer.BakeMesh(Mesh)"/> -> mesh in the renderer's LOCAL space, then the
|
||||
/// player's world scale is divided back out (BakeMesh bakes that scale IN; see PlayerScaler) so the
|
||||
/// convention world = transform.localToWorldMatrix holds at ANY size — the same fixup SkinnedColliderBaker
|
||||
/// applies, and the unit-scale mesh MeshPainter borrows from it.
|
||||
/// 2. Column ray-stabbing in local space: each (x,z) grid column collects the Y where the mesh
|
||||
/// surface crosses it; parity (odd # of crossings below a voxel center) marks interior voxels.
|
||||
/// This is the same XZ triangle rasterization MeshPainter.GetIslandMask uses for UV islands.
|
||||
@@ -74,6 +76,7 @@ public class ConcealmentMeter : MonoBehaviour
|
||||
private Vector3[] _verts;
|
||||
private int[] _tris;
|
||||
private float _timer;
|
||||
private readonly List<Vector3> _vbuf = new List<Vector3>(); // reused scale-fixup scratch; nothing allocated per eval
|
||||
|
||||
// Per-column Y crossings (index = iz * nx + ix). Reused across evals; sizes grow as needed.
|
||||
private List<float>[] _columns;
|
||||
@@ -122,6 +125,17 @@ public class ConcealmentMeter : MonoBehaviour
|
||||
if (!targetRenderer) return;
|
||||
|
||||
targetRenderer.BakeMesh(_baked);
|
||||
|
||||
// BakeMesh freezes the bone deformation — which already carries the player's world scale (PlayerScaler)
|
||||
// — into the mesh. Everything below treats the bake as unit-scale LOCAL geometry and raises it to world
|
||||
// via targetRenderer.localToWorldMatrix, which re-applies that same scale. Divide it back out first,
|
||||
// else a scaled player is measured at scale² (voxel world positions, broadphase box AND gizmos), which
|
||||
// also corrupts EmbeddedPercent. No-op at scale 1; the uniform divide is rotation-independent, which the
|
||||
// player's uniform scale guarantees. Mirrors SkinnedColliderBaker's identical fixup.
|
||||
Vector3 ls = targetRenderer.transform.lossyScale;
|
||||
if (ls.x != 1f || ls.y != 1f || ls.z != 1f)
|
||||
RescaleBakedToUnitScale(ls);
|
||||
|
||||
_verts = _baked.vertices;
|
||||
_tris = _baked.triangles;
|
||||
if (_verts.Length == 0 || _tris.Length < 3) return;
|
||||
@@ -199,6 +213,24 @@ public class ConcealmentMeter : MonoBehaviour
|
||||
HasResult = true;
|
||||
}
|
||||
|
||||
/// <summary>Divides the player's world scale back out of the freshly baked mesh so it is true unit-scale
|
||||
/// local geometry (the space this class raises to world with). Reuses <see cref="_vbuf"/> — no per-eval alloc.</summary>
|
||||
private void RescaleBakedToUnitScale(Vector3 lossyScale)
|
||||
{
|
||||
float ix = lossyScale.x != 0f ? 1f / lossyScale.x : 0f;
|
||||
float iy = lossyScale.y != 0f ? 1f / lossyScale.y : 0f;
|
||||
float iz = lossyScale.z != 0f ? 1f / lossyScale.z : 0f;
|
||||
_baked.GetVertices(_vbuf);
|
||||
for (int i = 0; i < _vbuf.Count; i++)
|
||||
{
|
||||
Vector3 v = _vbuf[i];
|
||||
v.x *= ix; v.y *= iy; v.z *= iz;
|
||||
_vbuf[i] = v;
|
||||
}
|
||||
_baked.SetVertices(_vbuf);
|
||||
_baked.RecalculateBounds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rasterizes every triangle into the XZ column grid; each column accumulates the Y values
|
||||
/// where the surface crosses it (one per triangle whose XZ projection covers the column center).
|
||||
|
||||
Reference in new issue
Block a user