Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
simlrh committed Jul 1, 2016
0 parents commit 8c50f8a
Show file tree
Hide file tree
Showing 7 changed files with 436 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "vendor/wiiuse"]
path = vendor/wiiuse
url = https://github.com/rpavlik/wiiuse.git
30 changes: 30 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 2.8.12)
project(WiimotePlugin)

# in the CMake GUI or command line.
find_package(osvr REQUIRED)

set(BUILD_WIIUSE_SHARED_LIB OFF CACHE BOOL "Should we build as a shared library (dll/so)?")
add_definitions("-DWIIUSE_STATIC")
set(BUILD_EXAMPLE OFF CACHE BOOL "Should we build the example app?")
set(BUILD_EXAMPLE_SDL OFF CACHE BOOL "Should we build the SDL-based example app?")
set(INSTALL_EXAMPLES OFF CACHE BOOL "Should we install the example apps?")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/vendor/wiiuse/cmake")

add_subdirectory("vendor/wiiuse")

osvr_convert_json(je_nourish_wiimote_json
je_nourish_wiimote.json
"${CMAKE_CURRENT_BINARY_DIR}/je_nourish_wiimote_json.h")

include_directories("${CMAKE_CURRENT_BINARY_DIR}")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/vendor/wiiuse/src")

osvr_add_plugin(NAME je_nourish_wiimote
CPP # indicates we'd like to use the C++ wrapper
SOURCES
je_nourish_wiimote.cpp
"${CMAKE_CURRENT_BINARY_DIR}/je_nourish_wiimote_json.h")

# If you use other libraries, find them and add a line like:
target_link_libraries(je_nourish_wiimote wiiuse)
15 changes: 15 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
OSVR-Wiimote
Copyright (C) 2016 Steve Le Roy Harris

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# OSVR Wiimote Plugin {#WiimotePluginReadme}

An OSVR plugin providing up to four Wii Remote + Nuncuk devices via the wiiuse library. There's one orientation only tracker per wiimote or nunchuk, although yaw is only available if using the sensor bar.

Default mappings are for one wiimote in the right hand and nunchuk in the left, but it's more fun with a nunchuk in each hand!

git clone https://github.com/simlrh/OSVR-Wiimote
cd OSVR-Wiimote
git submodule init
git submoule update

Then follow the [standard OSVR plugin build instructions](http://resource.osvr.com/docs/OSVR-Core/TopicWritingDevicePlugin.html).
224 changes: 224 additions & 0 deletions je_nourish_wiimote.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// Internal Includes
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/PluginKit/TrackerInterfaceC.h>
#include <osvr/PluginKit/AnalogInterfaceC.h>
#include <osvr/PluginKit/ButtonInterfaceC.h>

// Generated JSON header file
#include "je_nourish_wiimote_json.h"

// Library/third-party includes
#include "wiiuse.h"

// Standard includes
#include <iostream>
#define _USE_MATH_DEFINES
#include <Math.h>

#define MAX_WIIMOTES 4
#define TRACKERS_PER_WIIMOTE 2
#define BUTTONS_PER_WIIMOTE 13
#define ANALOG_PER_WIIMOTE 5

// Anonymous namespace to avoid symbol collision
namespace {

class WiimoteDevice {
public:
WiimoteDevice(OSVR_PluginRegContext ctx) {
int found, connected;

m_wiimotes = wiiuse_init(MAX_WIIMOTES);
found = wiiuse_find(m_wiimotes, MAX_WIIMOTES, 5);
connected = wiiuse_connect(m_wiimotes, MAX_WIIMOTES);

wiiuse_set_leds(m_wiimotes[0], WIIMOTE_LED_1);
wiiuse_set_leds(m_wiimotes[1], WIIMOTE_LED_2);
wiiuse_set_leds(m_wiimotes[2], WIIMOTE_LED_3);
wiiuse_set_leds(m_wiimotes[3], WIIMOTE_LED_4);

wiiuse_motion_sensing(m_wiimotes[0], 1);
wiiuse_motion_sensing(m_wiimotes[1], 1);
wiiuse_motion_sensing(m_wiimotes[2], 1);
wiiuse_motion_sensing(m_wiimotes[3], 1);

/// Create the initialization options
OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

osvrDeviceTrackerConfigure(opts, &m_tracker);
osvrDeviceAnalogConfigure(opts, &m_analog, 20);
osvrDeviceButtonConfigure(opts, &m_button, 52);

/// Create the device token with the options
m_dev.initAsync(ctx, "WiimoteDevice", opts);

/// Send JSON descriptor
m_dev.sendJsonDescriptor(je_nourish_wiimote_json);

/// Register update callback
m_dev.registerUpdateCallback(this);
}

~WiimoteDevice() {
wiiuse_cleanup(m_wiimotes, MAX_WIIMOTES);
}

OSVR_ReturnCode update() {
struct wiimote_t* wm;
OSVR_Vec3 wm_rpy;
OSVR_Quaternion wm_quaternion;
OSVR_Vec3 nc_rpy;
OSVR_Quaternion nc_quaternion;

osvrVec3Zero(&wm_rpy);
osvrQuatSetIdentity(&wm_quaternion);
osvrVec3Zero(&nc_rpy);
osvrQuatSetIdentity(&nc_quaternion);

if (wiimote_connected()) {
wiiuse_poll(m_wiimotes, MAX_WIIMOTES);

OSVR_ButtonState buttons[BUTTONS_PER_WIIMOTE * MAX_WIIMOTES];
OSVR_AnalogState analog[ANALOG_PER_WIIMOTE * MAX_WIIMOTES];

for (int i = 0; i < MAX_WIIMOTES; i++) {
wm = m_wiimotes[i];

if (wm->event == WIIUSE_EVENT) {
buttons[BUTTONS_PER_WIIMOTE*i + 0] = IS_PRESSED(wm, WIIMOTE_BUTTON_A);
buttons[BUTTONS_PER_WIIMOTE*i + 1] = IS_PRESSED(wm, WIIMOTE_BUTTON_B);
buttons[BUTTONS_PER_WIIMOTE*i + 2] = IS_PRESSED(wm, WIIMOTE_BUTTON_UP);
buttons[BUTTONS_PER_WIIMOTE*i + 3] = IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN);
buttons[BUTTONS_PER_WIIMOTE*i + 4] = IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT);
buttons[BUTTONS_PER_WIIMOTE*i + 5] = IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT);
buttons[BUTTONS_PER_WIIMOTE*i + 6] = IS_PRESSED(wm, WIIMOTE_BUTTON_ONE);
buttons[BUTTONS_PER_WIIMOTE*i + 7] = IS_PRESSED(wm, WIIMOTE_BUTTON_TWO);
buttons[BUTTONS_PER_WIIMOTE*i + 8] = IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS);
buttons[BUTTONS_PER_WIIMOTE*i + 9] = IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS);
buttons[BUTTONS_PER_WIIMOTE*i + 10] = IS_PRESSED(wm, WIIMOTE_BUTTON_HOME);

if (WIIUSE_USING_ACC(wm)) {

osvrVec3SetX(&wm_rpy, -wm->orient.roll * M_PI / 180);
osvrVec3SetY(&wm_rpy, -wm->orient.pitch * M_PI / 180);
osvrVec3SetZ(&wm_rpy, -wm->orient.yaw * M_PI / 180);

WiimoteDevice::quaternionFromRPY(&wm_rpy, &wm_quaternion);

osvrDeviceTrackerSendOrientation(m_dev, m_tracker, &wm_quaternion, (TRACKERS_PER_WIIMOTE * i));
}

if (WIIUSE_USING_IR(wm)) {
analog[ANALOG_PER_WIIMOTE*i + 0] = wm->ir.x;
analog[ANALOG_PER_WIIMOTE*i + 1] = wm->ir.y;
analog[ANALOG_PER_WIIMOTE*i + 2] = wm->ir.z;
}
else {
analog[ANALOG_PER_WIIMOTE*i + 0] = 0;
analog[ANALOG_PER_WIIMOTE*i + 1] = 0;
analog[ANALOG_PER_WIIMOTE*i + 2] = 0;
}

if (wm->exp.type == EXP_NUNCHUK || wm->exp.type == EXP_MOTION_PLUS_NUNCHUK) {
struct nunchuk_t* nc = (nunchuk_t*)&wm->exp.nunchuk;

buttons[BUTTONS_PER_WIIMOTE*i + 11] = IS_PRESSED(wm, NUNCHUK_BUTTON_C);
buttons[BUTTONS_PER_WIIMOTE*i + 12] = IS_PRESSED(wm, NUNCHUK_BUTTON_Z);

analog[ANALOG_PER_WIIMOTE*i + 3] = nc->js.x;
analog[ANALOG_PER_WIIMOTE*i + 4] = nc->js.y;

osvrVec3SetX(&nc_rpy, -nc->orient.roll * M_PI / 180);
osvrVec3SetY(&nc_rpy, -nc->orient.pitch * M_PI / 180);
osvrVec3SetZ(&nc_rpy, -nc->orient.yaw * M_PI / 180);

WiimoteDevice::quaternionFromRPY(&nc_rpy, &nc_quaternion);

osvrDeviceTrackerSendOrientation(m_dev, m_tracker, &nc_quaternion, (TRACKERS_PER_WIIMOTE * i) + 1);
}
else {
buttons[BUTTONS_PER_WIIMOTE*i + 11] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 12] = false;
analog[ANALOG_PER_WIIMOTE*i + 3] = 0;
analog[ANALOG_PER_WIIMOTE*i + 4] = 0;
}
}
else {
buttons[BUTTONS_PER_WIIMOTE*i + 0] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 1] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 2] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 3] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 4] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 5] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 6] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 7] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 8] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 9] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 10] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 11] = false;
buttons[BUTTONS_PER_WIIMOTE*i + 12] = false;
}
}

osvrDeviceAnalogSetValues(m_dev, m_analog, analog, 20);
osvrDeviceButtonSetValues(m_dev, m_button, buttons, 52);
}

return OSVR_RETURN_SUCCESS;
}

private:
bool wiimote_connected() {
for (int i = 0; i < MAX_WIIMOTES; i++) {
if (m_wiimotes[i] && WIIMOTE_IS_CONNECTED(m_wiimotes[i])) {
return true;
}
}
return false;
}
static void quaternionFromRPY(OSVR_Vec3* rpy, OSVR_Quaternion* quaternion) {
double r = osvrVec3GetX(rpy);
double p = osvrVec3GetY(rpy);
double y = osvrVec3GetZ(rpy);

osvrQuatSetZ(quaternion, sin(r / 2) * cos(p / 2) * cos(y / 2) - cos(r / 2) * sin(p / 2) * sin(y / 2));
osvrQuatSetX(quaternion, cos(r / 2) * sin(p / 2) * cos(y / 2) + sin(r / 2) * cos(p / 2) * sin(y / 2));
osvrQuatSetY(quaternion, cos(r / 2) * cos(p / 2) * sin(y / 2) - sin(r / 2) * sin(p / 2) * cos(y / 2));
osvrQuatSetW(quaternion, cos(r / 2) * cos(p / 2) * cos(y / 2) + sin(r / 2) * sin(p / 2) * sin(y / 2));
}

wiimote** m_wiimotes;
osvr::pluginkit::DeviceToken m_dev;
OSVR_TrackerDeviceInterface m_tracker;
OSVR_AnalogDeviceInterface m_analog;
OSVR_ButtonDeviceInterface m_button;
};

class HardwareDetection {
public:
HardwareDetection() : m_found(false) {}
OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx) {

if (!m_found) {
m_found = true;

osvr::pluginkit::registerObjectForDeletion(
ctx, new WiimoteDevice(ctx));
}
return OSVR_RETURN_SUCCESS;
}

private:
bool m_found;

};
} // namespace

OSVR_PLUGIN(je_nourish_wiimote) {
osvr::pluginkit::PluginContext context(ctx);

/// Register a detection callback function object.
context.registerHardwareDetectCallback(new HardwareDetection());

return OSVR_RETURN_SUCCESS;
}
Loading

0 comments on commit 8c50f8a

Please sign in to comment.