mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
Fix moving average quaternion desync & smoothing (#1351)
This commit is contained in:
@@ -29,8 +29,7 @@ class QuaternionMovingAverage(
|
||||
private var latestQuaternion = IDENTITY
|
||||
private var smoothingQuaternion = IDENTITY
|
||||
private val fpsTimer = if (VRServer.instanceInitialized) VRServer.instance.fpsTimer else NanoTimer()
|
||||
private var frameCounter = 0
|
||||
private var lastAmt = 0f
|
||||
private var timeSinceUpdate = 0f
|
||||
|
||||
init {
|
||||
// amount should range from 0 to 1.
|
||||
@@ -71,28 +70,15 @@ class QuaternionMovingAverage(
|
||||
filteredQuaternion = filteredQuaternion.interpR(quatBuf, amt)
|
||||
}
|
||||
} else if (type == TrackerFilters.SMOOTHING) {
|
||||
// Increase every update for linear interpolation
|
||||
frameCounter++
|
||||
// Make it framerate-independent
|
||||
timeSinceUpdate += fpsTimer.timePerFrame
|
||||
|
||||
// Calculate the slerp factor based off the smoothFactor and smoothingCounter
|
||||
var amt = smoothFactor * frameCounter
|
||||
|
||||
// Make it framerate-independent
|
||||
amt *= fpsTimer.timePerFrame
|
||||
|
||||
// Be at least last amount to not rollback
|
||||
amt = amt.coerceAtLeast(lastAmt)
|
||||
|
||||
// limit to 1 to not overshoot
|
||||
amt = amt.coerceAtMost(1f)
|
||||
|
||||
lastAmt = amt
|
||||
val amt = (smoothFactor * timeSinceUpdate).coerceAtMost(1f)
|
||||
|
||||
// Smooth towards the target rotation by the slerp factor
|
||||
filteredQuaternion = smoothingQuaternion.interpR(latestQuaternion, amt)
|
||||
} else {
|
||||
// No filtering; just keep track of rotations (for going over 180 degrees)
|
||||
filteredQuaternion = latestQuaternion.twinNearest(smoothingQuaternion)
|
||||
}
|
||||
|
||||
filteringImpact = latestQuaternion.angleToR(filteredQuaternion)
|
||||
@@ -108,21 +94,20 @@ class QuaternionMovingAverage(
|
||||
// Gets and stores the rotation between the last 2 quaternions
|
||||
rotBuffer?.add(latestQuaternion.inv().times(q))
|
||||
} else if (type == TrackerFilters.SMOOTHING) {
|
||||
frameCounter = 0
|
||||
lastAmt = 0f
|
||||
timeSinceUpdate = 0f
|
||||
smoothingQuaternion = filteredQuaternion
|
||||
} else {
|
||||
smoothingQuaternion = filteredQuaternion
|
||||
// No filtering; just keep track of rotations (for going over 180 degrees)
|
||||
filteredQuaternion = q.twinNearest(filteredQuaternion)
|
||||
}
|
||||
|
||||
latestQuaternion = q
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun resetQuats(q: Quaternion) {
|
||||
if (type == TrackerFilters.PREDICTION) {
|
||||
rotBuffer?.clear()
|
||||
latestQuaternion = q
|
||||
}
|
||||
rotBuffer?.clear()
|
||||
latestQuaternion = q
|
||||
filteredQuaternion = q
|
||||
addQuaternion(q)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user