Skip to content

Commit

Permalink
Quaternions at this precision can't represent very slow rotations sam…
Browse files Browse the repository at this point in the history
…pled at very high frequency, so now there's "stochastic small rotations" -- very small rotations will pseudorandomly be rounded up to a small rotation that *can* be represented by a Quaternion, or down to 0. The probability of being rounded up or down is based on the size of the very small rotation compared to our minimum very small rotation. Over time, this means small / slow rotations get represented pretty well.

The user can comment out #define GMH_STOCHASTIC_SMALL_ROTATIONS_ENABLED in order to disable this.
  • Loading branch information
JibbSmart committed Mar 8, 2023
1 parent 5277cee commit 39af32c
Showing 1 changed file with 21 additions and 1 deletion.
22 changes: 21 additions & 1 deletion GamepadMotion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
#include <math.h>
#include <algorithm> // std::min, std::max and std::clamp

#define GMH_STOCHASTIC_SMALL_ROTATIONS_ENABLED
#ifdef GMH_STOCHASTIC_SMALL_ROTATIONS_ENABLED
#include <cstdlib> // std::rand
#endif

// You don't need to look at these. These will just be used internally by the GamepadMotion class declared below.
// You can ignore anything in namespace GamepadMotionHelpers.
class GamepadMotionSettings;
Expand Down Expand Up @@ -565,7 +570,20 @@ namespace GamepadMotionHelpers
const Vec axis = Vec(inGyroX, inGyroY, inGyroZ);
const Vec accel = Vec(inAccelX, inAccelY, inAccelZ);
const float angleSpeed = axis.Length() * (float)M_PI / 180.0f;
const float angle = angleSpeed * deltaTime;
float angle = angleSpeed * deltaTime;

#ifdef GMH_STOCHASTIC_SMALL_ROTATIONS_ENABLED
// because cos angle for small angles will hit 1 very quickly and do nothing for slow rotations, we go stochastic for small values
static const float stochasticThreshold = 0.0005f;
const float absAngle = std::abs(angle);
if (absAngle < stochasticThreshold && absAngle > 0.0f)
{
const float random01 = rand() / (RAND_MAX + 1.0f);
const float angleSign = angle > 0.0f ? 1.0f : -1.0f;
const float probability = absAngle / stochasticThreshold;
angle = angleSign * (random01 < probability ? stochasticThreshold : 0.0f);
}
#endif

// rotate
Quat rotation = AngleAxis(angle, axis.x, axis.y, axis.z);
Expand Down Expand Up @@ -1244,3 +1262,5 @@ inline void GamepadMotion::GetCalibratedSensor(float& gyroOffsetX, float& gyroOf
gyroOffsetZ = GyroCalibration.Z * inverseSamples;
accelMagnitude = GyroCalibration.AccelMagnitude * inverseSamples;
}

#undef GMH_STOCHASTIC_SMALL_ROTATIONS_ENABLED

0 comments on commit 39af32c

Please sign in to comment.