#1166 Static prims no longer flagged as moving objects by float noise (rain / snow inside buildings) #1167

Closed
TheSlowly wants to merge 1 commit from TheSlowly/Slipstream:static-mover-pose-jitter into main
Collaborator

Fixes #1166 and #1165. This is the follow-up to #1145: the remaining indoor leak after its PR.

Cause: indoors, the camera distance to the surrounding prims is clamped to 1 cm, so LL's ease never passes its end test and the eased pose flips by single ULPs. The bit-exact pose compare treated that as motion. The building became a dynamic caster, dropped out of the weather roof map for about 2 s at a time, and rain and snow fell inside. The avatar's exposure read 1 during those windows, so it built a snow coat (#1165).

Change:

  • LLDrawable::updateXform snaps an ease that is within float rounding of its target (RenderVKEaseSnapAtTarget).
  • Mover classification compares against a reference pose with #1007's near-unchanged measure, 2 mm near the camera (RenderVKShadowMoverPoseThreshold, 0 = the old exact rule). The comparison accumulates, so slow movers are still caught. The GPU pose upload stays exact.
  • RenderVKMoverDiag shows a motion rate next to the pose-change rate.

Tested in-world: a house that rained inside stays covered, and the avatar's indoor exposure holds at 0.

Fixes #1166 and #1165. This is the follow-up to #1145: the remaining indoor leak after its PR. Cause: indoors, the camera distance to the surrounding prims is clamped to 1 cm, so LL's ease never passes its end test and the eased pose flips by single ULPs. The bit-exact pose compare treated that as motion. The building became a dynamic caster, dropped out of the weather roof map for about 2 s at a time, and rain and snow fell inside. The avatar's exposure read 1 during those windows, so it built a snow coat (#1165). Change: - `LLDrawable::updateXform` snaps an ease that is within float rounding of its target (`RenderVKEaseSnapAtTarget`). - Mover classification compares against a reference pose with #1007's near-unchanged measure, 2 mm near the camera (`RenderVKShadowMoverPoseThreshold`, 0 = the old exact rule). The comparison accumulates, so slow movers are still caught. The GPU pose upload stays exact. - `RenderVKMoverDiag` shows a motion rate next to the pose-change rate. Tested in-world: a house that rained inside stays covered, and the avatar's indoor exposure holds at 0.
A static building's prims kept flipping into the #567 dynamic-caster class
(RenderVKWeatherSnowDepthDebug magenta), which drops them from the weather roof
map (static casters only) for RenderVKShadowMoverSettleSecs at a time: rain and
snow fell indoors, and an avatar standing inside got exposure 1 in those windows
and a snow coat (#1165).

Cause: LLDrawable::updateXform's damped ease never ends for a settled drawable
when the camera is inside its bounds. vkStampMoveVisibility stamps
mDistanceWRTCamera = max(0.01, distance - radius), so the walls / floors around
the camera get 0.01 m and LL's end test (dist^2 < 1e-6 * camdist^2 = 1e-10) is
below the noise of nlerp re-rounding a reached rotation ((1 - dot) * 10 ~ 1e-6).
In a float simulation of that loop ~20% of settled rotations never leave the
move list. While on it the eased rotation flips ULPs (vkRenderLocalPose reads
the drawable xform), an active root re-queues its whole linkset every frame, and
refreshObjectPose's bit-exact compare reports each flip as a pose change: a mover.

- LLDrawable::updateXform: an ease already within float rounding of the target
  (1e-6 relative per position / scale component, 1e-6 per quaternion component)
  snaps and leaves the move list. RenderVKEaseSnapAtTarget (on) for A/B.
- Mover classification ignores sub-threshold pose changes: refreshObjectPose
  reports the object's first row before / after; LLCleanIngest::poseMoved
  measures it against a reference pose (the row before the first change since
  the object was last static, then the last noted motion; erased on settle,
  cleared on an origin shift), so a slow mover's steps accumulate. Measure and
  threshold follow #1007's near-unchanged pose: translation + rotation x lever
  (here the object's own half-size via the scaled axes), 2 mm within 10 m of the
  camera, growing linearly beyond, never below ~8 ULPs of the coordinates; the
  spin record separately. Noise changes still upload the exact matrix but no
  longer start a mover or invalidate static shadow tiles.
  RenderVKShadowMoverPoseThreshold (0.002; 0 = any bit change, the old rule).
- Diag: RenderVKMoverDiag prints "motion N/s" next to the pose rate; hitch
  counter movedPoseNoise.

Test-Plan: observatory, rain, RenderVKShadowMoverSettleSecs 2: no rain or snow
indoors, RenderVKWeatherSnowDepthDebug stays yellow on the building; RenderVKMoverDiag
shows pose changes with motion ~0/s for it. Parcel snow, stand indoors a few
minutes: no coat; walk out: the coat builds; walk back in: it melts. Movers still
classified: a vehicle, a scripted llSetPos / llSetRot mover, a door swing, slow
keyframed motion, a sat-on vehicle. A/B with RenderVKShadowMoverPoseThreshold 0
and RenderVKEaseSnapAtTarget 0.
Author
Collaborator

Merged into main (rebased) as ad6e8c6adf.

Merged into main (rebased) as ad6e8c6adf.
TheSlowly closed this pull request 2026-10-27 22:09:59 +00:00

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream!1167
No description provided.