Implemented gyroscope controls, no camera rotation and no filtering algorithm yet

This commit is contained in:
Sergii Pylypenko 2018-10-19 14:29:10 +03:00
parent 64e0c6312e
commit 572132be46
5 changed files with 171 additions and 4 deletions

View File

@ -202,7 +202,8 @@ bool EventHandler::OnEvent (const SEvent &event)
event.EventType == EET_TOUCH_INPUT_EVENT ||
event.EventType == EET_KEY_INPUT_EVENT ||
event.EventType == EET_JOYSTICK_INPUT_EVENT ||
event.EventType == EET_ACCELEROMETER_EVENT)
event.EventType == EET_ACCELEROMETER_EVENT ||
event.EventType == EET_GYROSCOPE_EVENT)
{
// Remember the mouse position
if (event.EventType == EET_MOUSE_INPUT_EVENT &&

View File

@ -937,6 +937,7 @@ bool InputManager::masterPlayerOnly() const
*/
EventPropagation InputManager::input(const SEvent& event)
{
const float ORIENTATION_MULTIPLIER = 10.0f;
if (event.EventType == EET_JOYSTICK_INPUT_EVENT)
{
// Axes - FIXME, instead of checking all of them, ask the bindings
@ -1238,7 +1239,29 @@ EventPropagation InputManager::input(const SEvent& event)
float factor = UserConfigParams::m_multitouch_tilt_factor;
factor = std::max(factor, 0.1f);
device->updateAxisX(float(event.AccelerometerEvent.Y) / factor);
if (UserConfigParams::m_multitouch_controls == MULTITOUCH_CONTROLS_GYROSCOPE)
{
device->updateOrientationFromAccelerometer(event.AccelerometerEvent.X, event.AccelerometerEvent.Y);
device->updateAxisX(device->getOrientation() * ORIENTATION_MULTIPLIER / factor);
}
else
{
device->updateAxisX(float(event.AccelerometerEvent.Y) / factor);
}
}
}
else if (event.EventType == EET_GYROSCOPE_EVENT)
{
MultitouchDevice* device = m_device_manager->getMultitouchDevice();
if (device && device->isGyroscopeActive())
{
m_device_manager->updateMultitouchDevice();
float factor = UserConfigParams::m_multitouch_tilt_factor;
factor = std::max(factor, 0.1f);
device->updateOrientationFromGyroscope(event.GyroscopeEvent.Z);
device->updateAxisX(device->getOrientation() * ORIENTATION_MULTIPLIER / factor);
}
}

View File

@ -171,6 +171,9 @@ void MultitouchDevice::reset()
event.x = 0;
event.y = 0;
}
m_orientation = 0.0f;
m_gyro_time = 0.0;
} // reset
// ----------------------------------------------------------------------------
@ -212,6 +215,45 @@ bool MultitouchDevice::isAccelerometerActive()
return false;
}
// ----------------------------------------------------------------------------
/** Activates gyroscope
*/
void MultitouchDevice::activateGyroscope()
{
#ifdef ANDROID
if (!m_android_device->isGyroscopeActive())
{
m_android_device->activateGyroscope(1.0f / 60); // Assume 60 FPS, some phones can do 90 and 120 FPS but we won't handle them now
}
#endif
}
// ----------------------------------------------------------------------------
/** Deativates gyroscope
*/
void MultitouchDevice::deactivateGyroscope()
{
#ifdef ANDROID
if (m_android_device->isGyroscopeActive())
{
m_android_device->deactivateGyroscope();
}
#endif
}
// ----------------------------------------------------------------------------
/** Get gyroscope state
* \return true if gyroscope is active
*/
bool MultitouchDevice::isGyroscopeActive()
{
#ifdef ANDROID
return m_android_device->isGyroscopeActive();
#endif
return false;
}
// ----------------------------------------------------------------------------
/** The function that is executed when touch event occurs. It updates the
* buttons state when it's needed.
@ -382,6 +424,87 @@ void MultitouchDevice::updateAxisY(float value)
// ----------------------------------------------------------------------------
float MultitouchDevice::getOrientation()
{
return m_orientation;
}
// ----------------------------------------------------------------------------
void MultitouchDevice::updateOrientationFromAccelerometer(float x, float y)
{
const float ACCEL_DISCARD_THRESHOLD = 4.0f;
const float ACCEL_MULTIPLIER = 0.05f; // Slowly adjust the angle over time, this prevents shaking
const float ACCEL_CHANGE_THRESHOLD = 0.01f; // ~0.5 degrees
if (fabsf(x) + fabsf(y) < ACCEL_DISCARD_THRESHOLD)
{
// The device is flat on the table, cannot reliably determine the orientation
return;
}
float angle = atan2f(y, x);
if (angle > (M_PI / 2.0))
{
angle = (M_PI / 2.0);
}
if (angle < -(M_PI / 2.0))
{
angle = -(M_PI / 2.0);
}
float delta = angle - m_orientation;
delta *= ACCEL_MULTIPLIER;
if (delta > ACCEL_CHANGE_THRESHOLD)
{
delta = ACCEL_CHANGE_THRESHOLD;
}
if (delta < -ACCEL_CHANGE_THRESHOLD)
{
delta = -ACCEL_CHANGE_THRESHOLD;
}
m_orientation += delta;
//Log::warn("Accel", "X %03.4f Y %03.4f angle %03.4f delta %03.4f orientation %03.4f", x, y, angle, delta, m_orientation);
}
// ----------------------------------------------------------------------------
void MultitouchDevice::updateOrientationFromGyroscope(float z)
{
const float GYRO_SPEED_THRESHOLD = 0.005f;
double now = StkTime::getRealTime();
float timedelta = now - m_gyro_time;
m_gyro_time = now;
if (timedelta > 0.5f)
{
timedelta = 0.1f;
}
float angular_speed = -z;
if (fabsf(angular_speed) < GYRO_SPEED_THRESHOLD)
{
angular_speed = 0.0f;
}
m_orientation += angular_speed * timedelta;
if (m_orientation > (M_PI / 2.0))
{
m_orientation = (M_PI / 2.0);
}
if (m_orientation < -(M_PI / 2.0))
{
m_orientation = -(M_PI / 2.0);
}
//Log::warn("Gyro", "Z %03.4f angular_speed %03.4f delta %03.4f orientation %03.4f", z, angular_speed, angular_speed * timedelta, m_orientation);
}
// ----------------------------------------------------------------------------
/** Sends proper action for player controller depending on the button type
* and state.
* \param button The button that should be handled.

View File

@ -87,6 +87,9 @@ private:
* at the edge of button */
float m_deadzone_edge;
float m_orientation;
double m_gyro_time;
#ifdef ANDROID
/** Pointer to the Android irrlicht device */
CIrrDeviceAndroid* m_android_device;
@ -125,9 +128,16 @@ public:
void activateAccelerometer();
void deactivateAccelerometer();
bool isAccelerometerActive();
void activateGyroscope();
void deactivateGyroscope();
bool isGyroscopeActive();
void updateAxisX(float value);
void updateAxisY(float value);
float getOrientation();
void updateOrientationFromAccelerometer(float x, float y);
void updateOrientationFromGyroscope(float z);
void updateDeviceState(unsigned int event_id);
void updateController();
void updateConfigParams();

View File

@ -104,6 +104,11 @@ void RaceGUIMultitouch::close()
{
m_device->deactivateAccelerometer();
}
if (m_device->isGyroscopeActive())
{
m_device->deactivateGyroscope();
}
} // close
@ -120,6 +125,11 @@ void RaceGUIMultitouch::init()
{
m_device->activateAccelerometer();
}
if (UserConfigParams::m_multitouch_controls == MULTITOUCH_CONTROLS_GYROSCOPE)
{
m_device->activateAccelerometer();
m_device->activateGyroscope();
}
const float scale = UserConfigParams::m_multitouch_scale;
@ -155,7 +165,7 @@ void RaceGUIMultitouch::init()
m_height = (unsigned int)(2 * col_size + margin / 2);
if (m_device->isAccelerometerActive())
if (m_device->isAccelerometerActive() || m_device->isGyroscopeActive())
{
m_device->addButton(BUTTON_UP_DOWN,
int(steering_accel_x), int(steering_accel_y),