Spinning linksets (llTargetOmega): links drift out of sync / snap back to their unspun pose #418
Labels
No labels
amd
avatars
bug
builder
cannot-reproduce
crash
epic
feature
from-viewer
gl-removal
known-limitation
monitoring
parity
perf
platform
priority
critical
priority
high
priority
low
priority
medium
provenance
rendering
rt
status
in-progress
status
testing
status
up-next
triage
ui
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
sky_line/Slipstream#418
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A spinning linkset (almost certainly
llTargetOmega) gets its links out of sync: individual links occasionally appear to reset to their 0 / unspun position and then spin out of phase with the rest of the linkset. Reported by the owner, 2026-10-05.How target omega is drawn in Vulkan (code)
llcleaninstancestore.cpp,composeOwnedPose(~70-165), the "GPU TARGET OMEGA" block:applyAngularVelocity:rot = rot * dQ, accumulated inmAngularVelocityRot). VK instead factors the accumulated spin out of the pose (base = getRotation() * ~getAngularVelocityRot()) and gives the GPU the axis, pivot and phase. The vertex shader applies the spin with phasecam_time.w - t0, wheret0 = LLWorldClock::getTime() - spinner->getRotTime().LL side,
llviewerobject.cpp~2400-2424 (processUpdateMessagerotation path): when a new rotation arrives from the server,resetRot()zeroesmAngularVelocityRotand the rot time, thensetRotation(new_rot * mAngularVelocityRot). When only the angular velocity changes,resetRotTime()(orresetRot()for physical objects).Likely cause
Each link is a separate instance, re-composed only when that instance is visited (ingest sweep / dirty / mover refresh). A link's spin phase depends on its spinner's
getRotTime()and accumulated rotation, which change when the server sends a rotation or omega update (resetRot/resetRotTime):t0keeps the old phase. That link jumps (looks like a "reset to 0"), and then it's offset from the others.resetRot, child instances (which use the root's base and rot time) aren't re-composed in the same frame. They keep the oldt0and base until their own sweep visit, so they drift out of phase with the root and each other.isOmegaSpinnerflips around the threshold (> 0.00001) for slow spins, switching a link between the CPU and GPU paths.Fix direction
getRotTime()or accumulated-rotation reset as a spin-record change, not only an axis change, sot0and the base are rewritten together.t0and base.t0that differs from the root's.Repro
llTargetOmega(<0,0,1>, 1.0, 1.0)in the root.