Skip to content
Permalink
Browse files

WiimoteEmu: Allow shake frequency and intensity to be configured. Oth…

…er minor cleanups.
  • Loading branch information...
jordan-woyak committed Mar 29, 2019
1 parent 635fd8c commit c89ddf8cba9c6b19d59e2db1896292797163c54c
Showing with 285 additions and 313 deletions.
  1. +0 −1 Source/Core/Core/CMakeLists.txt
  2. +0 −33 Source/Core/Core/Config/WiimoteInputSettings.cpp
  3. +0 −31 Source/Core/Core/Config/WiimoteInputSettings.h
  4. +0 −2 Source/Core/Core/Core.vcxproj
  5. +1 −7 Source/Core/Core/Core.vcxproj.filters
  6. +25 −81 Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp
  7. +3 −33 Source/Core/Core/HW/WiimoteEmu/Dynamics.h
  8. +1 −3 Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp
  9. +11 −25 Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.cpp
  10. +2 −11 Source/Core/Core/HW/WiimoteEmu/Extension/Nunchuk.h
  11. +7 −51 Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp
  12. +2 −11 Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h
  13. +1 −1 Source/Core/Core/State.cpp
  14. +89 −0 Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp
  15. +19 −1 Source/Core/DolphinQt/Config/Mapping/MappingIndicator.h
  16. +15 −2 Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp
  17. +10 −1 Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h
  18. +1 −2 Source/Core/InputCommon/ControllerEmu/ControlGroup/Cursor.cpp
  19. +66 −2 Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.cpp
  20. +24 −0 Source/Core/InputCommon/ControllerEmu/ControlGroup/Force.h
  21. +5 −8 Source/Core/InputCommon/ControllerEmu/ControlGroup/MixedTriggers.cpp
  22. +1 −4 Source/Core/InputCommon/ControllerEmu/ControlGroup/Slider.cpp
  23. +1 −1 Source/Core/InputCommon/ControllerEmu/ControlGroup/Triggers.cpp
  24. +1 −2 Source/Core/InputCommon/ControllerEmu/StickGate.cpp
@@ -30,7 +30,6 @@ add_library(core
Config/NetplaySettings.cpp
Config/SYSCONFSettings.cpp
Config/UISettings.cpp
Config/WiimoteInputSettings.cpp
ConfigLoaders/BaseConfigLoader.cpp
ConfigLoaders/GameConfigLoader.cpp
ConfigLoaders/IsSettingSaveable.cpp

This file was deleted.

This file was deleted.

@@ -56,7 +56,6 @@
<ClCompile Include="ConfigLoaders\MovieConfigLoader.cpp" />
<ClCompile Include="ConfigLoaders\NetPlayConfigLoader.cpp" />
<ClCompile Include="ConfigManager.cpp" />
<ClCompile Include="Config\WiimoteInputSettings.cpp" />
<ClCompile Include="Core.cpp" />
<ClCompile Include="CoreTiming.cpp" />
<ClCompile Include="Debugger\Debugger_SymbolMap.cpp" />
@@ -327,7 +326,6 @@
<ClInclude Include="ConfigLoaders\NetPlayConfigLoader.h" />
<ClInclude Include="ConfigManager.h" />
<ClInclude Include="Config\UISettings.h" />
<ClInclude Include="Config\WiimoteInputSettings.h" />
<ClInclude Include="Core.h" />
<ClInclude Include="CoreTiming.h" />
<ClInclude Include="Debugger\Debugger_SymbolMap.h" />
@@ -874,9 +874,6 @@
<ClCompile Include="Config\UISettings.cpp">
<Filter>Config</Filter>
</ClCompile>
<ClCompile Include="Config\WiimoteInputSettings.cpp">
<Filter>Config</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64\RegCache\FPURegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\RegCache\GPRRegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\RegCache\JitRegCache.cpp" />
@@ -1592,9 +1589,6 @@
<ClInclude Include="Config\UISettings.h">
<Filter>Config</Filter>
</ClInclude>
<ClInclude Include="Config\WiimoteInputSettings.h">
<Filter>Config</Filter>
</ClInclude>
<ClInclude Include="HW\WiimoteEmu\I2CBus.h">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu</Filter>
</ClInclude>
@@ -1638,4 +1632,4 @@
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>
@@ -8,8 +8,6 @@

#include "Common/MathUtil.h"
#include "Core/Config/SYSCONFSettings.h"
#include "Core/Config/WiimoteInputSettings.h"
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "InputCommon/ControllerEmu/ControlGroup/Buttons.h"
#include "InputCommon/ControllerEmu/ControlGroup/Cursor.h"
@@ -18,11 +16,6 @@

namespace
{
constexpr int SHAKE_FREQ = 6;
// Frame count of one up/down shake
// < 9 no shake detection in "Wario Land: Shake It"
constexpr int SHAKE_STEP_MAX = ::Wiimote::UPDATE_FREQ / SHAKE_FREQ;

// Given a velocity, acceleration, and maximum jerk value,
// calculate change in position after a stop in the shortest possible time.
// Used to smoothly adjust acceleration and come to complete stops at precise positions.
@@ -61,81 +54,32 @@ double CalculateStopDistance(double velocity, double max_accel)

namespace WiimoteEmu
{
Common::Vec3 EmulateShake(ControllerEmu::Buttons* const buttons_group, const double intensity,
u8* const shake_step)
void EmulateShake(PositionalState* state, ControllerEmu::Shake* const shake_group,
float time_elapsed)
{
// shake is a bitfield of X,Y,Z shake button states
static const unsigned int btns[] = {0x01, 0x02, 0x04};
unsigned int shake = 0;
buttons_group->GetState(&shake, btns);

Common::Vec3 accel;

for (std::size_t i = 0; i != accel.data.size(); ++i)
auto target_position = shake_group->GetState() * shake_group->GetIntensity() / 2;
for (std::size_t i = 0; i != target_position.data.size(); ++i)
{
if (shake & (1 << i))
{
accel.data[i] = std::sin(MathUtil::TAU * shake_step[i] / SHAKE_STEP_MAX) * intensity *
GRAVITY_ACCELERATION;
shake_step[i] = (shake_step[i] + 1) % SHAKE_STEP_MAX;
}
else
if (state->velocity.data[i] * std::copysign(1.f, target_position.data[i]) < 0 ||
state->position.data[i] / target_position.data[i] > 0.5)
{
shake_step[i] = 0;
target_position.data[i] *= -1;
}
}

return accel;
}

Common::Vec3 EmulateDynamicShake(DynamicData& dynamic_data,
ControllerEmu::Buttons* const buttons_group,
const DynamicConfiguration& config, u8* const shake_step)
{
// shake is a bitfield of X,Y,Z shake button states
static const unsigned int btns[] = {0x01, 0x02, 0x04};
unsigned int shake = 0;
buttons_group->GetState(&shake, btns);

Common::Vec3 accel;
// Time from "top" to "bottom" of one shake.
const auto travel_time = 1 / shake_group->GetFrequency() / 2;

for (std::size_t i = 0; i != accel.data.size(); ++i)
Common::Vec3 jerk;
for (std::size_t i = 0; i != target_position.data.size(); ++i)
{
if ((shake & (1 << i)) && dynamic_data.executing_frames_left[i] == 0)
{
dynamic_data.timing[i]++;
}
else if (dynamic_data.executing_frames_left[i] > 0)
{
accel.data[i] = std::sin(MathUtil::TAU * shake_step[i] / SHAKE_STEP_MAX) *
dynamic_data.intensity[i] * GRAVITY_ACCELERATION;
shake_step[i] = (shake_step[i] + 1) % SHAKE_STEP_MAX;
dynamic_data.executing_frames_left[i]--;
}
else if (shake == 0 && dynamic_data.timing[i] > 0)
{
if (dynamic_data.timing[i] > config.frames_needed_for_high_intensity)
{
dynamic_data.intensity[i] = config.high_intensity;
}
else if (dynamic_data.timing[i] < config.frames_needed_for_low_intensity)
{
dynamic_data.intensity[i] = config.low_intensity;
}
else
{
dynamic_data.intensity[i] = config.med_intensity;
}
dynamic_data.timing[i] = 0;
dynamic_data.executing_frames_left[i] = config.frames_to_execute;
}
else
{
shake_step[i] = 0;
}
const auto half_distance =
std::max(std::abs(target_position.data[i]), std::abs(state->position.data[i]));

jerk.data[i] = half_distance / std::pow(travel_time / 2, 3);
}

return accel;
ApproachPositionWithJerk(state, target_position, jerk, time_elapsed);
}

void EmulateTilt(RotationalState* state, ControllerEmu::Tilt* const tilt_group, float time_elapsed)
@@ -158,8 +102,8 @@ void EmulateSwing(MotionState* state, ControllerEmu::Force* swing_group, float t

// Note. Y/Z swapped because X/Y axis to the swing_group is X/Z to the wiimote.
// X is negated because Wiimote X+ is to the left.
ApproachPositionWithJerk(state, {-target.x, -target.z, target.y}, swing_group->GetMaxJerk(),
time_elapsed);
ApproachPositionWithJerk(state, {-target.x, -target.z, target.y},
Common::Vec3{1, 1, 1} * swing_group->GetMaxJerk(), time_elapsed);

// Just jump to our target angle scaled by our progress to the target position.
// TODO: If we wanted to be less hacky we could use ApproachAngleWithAccel.
@@ -248,19 +192,19 @@ void ApproachAngleWithAccel(RotationalState* state, const Common::Vec3& angle_ta
}

void ApproachPositionWithJerk(PositionalState* state, const Common::Vec3& position_target,
float max_jerk, float time_elapsed)
const Common::Vec3& max_jerk, float time_elapsed)
{
const auto stop_distance =
Common::Vec3(CalculateStopDistance(state->velocity.x, state->acceleration.x, max_jerk),
CalculateStopDistance(state->velocity.y, state->acceleration.y, max_jerk),
CalculateStopDistance(state->velocity.z, state->acceleration.z, max_jerk));
Common::Vec3(CalculateStopDistance(state->velocity.x, state->acceleration.x, max_jerk.x),
CalculateStopDistance(state->velocity.y, state->acceleration.y, max_jerk.y),
CalculateStopDistance(state->velocity.z, state->acceleration.z, max_jerk.z));

const auto offset = position_target - state->position;
const auto stop_offset = offset - stop_distance;

const Common::Vec3 jerk{std::copysign(max_jerk, stop_offset.x),
std::copysign(max_jerk, stop_offset.y),
std::copysign(max_jerk, stop_offset.z)};
const Common::Vec3 jerk{std::copysign(max_jerk.x, stop_offset.x),
std::copysign(max_jerk.y, stop_offset.y),
std::copysign(max_jerk.z, stop_offset.z)};

state->acceleration += jerk * time_elapsed;

@@ -17,15 +17,6 @@ namespace WiimoteEmu
{
constexpr double GRAVITY_ACCELERATION = 9.80665;

// Used for dynamic shake
// TODO: kill this.
struct DynamicData
{
std::array<int, 3> timing; // Hold length in frames for each axis
std::array<double, 3> intensity; // Swing or shake intensity
std::array<int, 3> executing_frames_left; // Number of frames to execute the intensity operation
};

struct PositionalState
{
Common::Vec3 position;
@@ -47,34 +38,13 @@ struct MotionState : PositionalState, RotationalState
// Build a rotational matrix from euler angles.
Common::Matrix33 GetRotationalMatrix(const Common::Vec3& angle);

void ApproachPositionWithJerk(PositionalState* state, const Common::Vec3& target, float max_jerk,
float time_elapsed);
void ApproachPositionWithJerk(PositionalState* state, const Common::Vec3& target,
const Common::Vec3& max_jerk, float time_elapsed);

void ApproachAngleWithAccel(RotationalState* state, const Common::Vec3& target, float max_accel,
float time_elapsed);

// Used for dynamic shake.
// This is used to pass in data that defines the dynamic action
// TODO: kill this
struct DynamicConfiguration
{
double low_intensity;
int frames_needed_for_low_intensity;

double med_intensity;
// Frames needed for med intensity can be calculated between high & low

double high_intensity;
int frames_needed_for_high_intensity;

int frames_to_execute; // How many frames should we execute the action for?
};

Common::Vec3 EmulateShake(ControllerEmu::Buttons* buttons_group, double intensity, u8* shake_step);

Common::Vec3 EmulateDynamicShake(DynamicData& dynamic_data, ControllerEmu::Buttons* buttons_group,
const DynamicConfiguration& config, u8* shake_step);

void EmulateShake(PositionalState* state, ControllerEmu::Shake* shake_group, float time_elapsed);
void EmulateTilt(RotationalState* state, ControllerEmu::Tilt* tilt_group, float time_elapsed);
void EmulateSwing(MotionState* state, ControllerEmu::Force* swing_group, float time_elapsed);

@@ -584,9 +584,7 @@ void Wiimote::DoState(PointerWrap& p)
// Dynamics
p.Do(m_swing_state);
p.Do(m_tilt_state);

// TODO: clean this up:
p.Do(m_shake_step);
p.Do(m_shake_state);

p.DoMarker("Wiimote");
}

0 comments on commit c89ddf8

Please sign in to comment.
You can’t perform that action at this time.