Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » ALLEGRO_HAPTIC or force feedback for Allegro

This thread is locked; no one can reply to it. rss feed Print
 1   2 
ALLEGRO_HAPTIC or force feedback for Allegro
Peter Wang
Member #23
April 2000

Jokes aside, al_get_joystick_num_sticks/axes/buttons can return zero as well, once we update the documentation. How many zero-input devices are there anyway? (not counting gimmicks which only draw power from the USB port) I assume the Rez trance vibrator, specifically, is just another game controller to the OS.

Haptic keyboard/mouse can be handled as you had already.

beoran
Member #12,636
March 2011

Well, I can't say for all operating systems, but the Rez presents itself to Linux in the driver I know of as a device separate from the input, with a separate API. This may be a reason, though to disregard it for now.

However, I have to admit that for all other haptic devices I know of on Linux, the haptic capabilities are a part of the properties of a generic input device. Also, it's probably true that it will be easier for the people who use the API if they can get the haptic device handle directly from the desired device. So, I'll follow your suggestion.

I'll change the proposed API so haptic capabilities will be linked to existing input devices. And for the rare case of a haptic device that has no input capabilities, we'll make a virtual joystick that has no axes, or perhaps a al_joystic_is_pure_haptic(). Also this makes it possible to link the coordinate system of the haptic device to the axes the joystick actually has. It does mean that we have to modify the Linux joystick driver to scan more than just /dev/input/js* to get the "virtual joysticks".

So the way to get a haptic device handle will then be the following:

ALLEGRO_HAPTIC * al_get_haptic_from_joystick(ALLEGRO_JOYSTICK *);
ALLEGRO_HAPTIC * al_get_haptic_from_keyboard(ALLEGRO_KEYBOARD *);
ALLEGRO_HAPTIC * al_get_haptic_from_display(ALLEGRO_DISPLAY *);
ALLEGRO_HAPTIC * al_get_haptic_from_mouse(ALLEGRO_MOUSE *);
ALLEGRO_HAPTIC * al_get_haptic_from_touch_input(ALLEGRO_TOUCH_INPUT *);

Hmm, almost makes me wish we had some kind of generic ALLEGRO_INPUT_DEVICE...

Edit: here is the adjusted proposal for haptic.h, also with ALLEGRO_HAPTIC_EFFECT_ID to simplify play and stop.

#SelectExpand
1/* ______ ___ ___ 2 * /\ _ \ /_ \ /_ \ 3 * \ \ \L\ \//\ \ //\ \ __ __ _ __ ___ 4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `/`'__/ __`\ 5 * \ \ /\ \ _\ _ _\ _/\ __//\ \L\ \ \ //\ \L\ \ 6 * \ _\ _/____/____\ ____\ ____ \ _\\ ____/ 7 * /_//_//____//____//____//___L\ /_/ /___/ 8 * /____/ 9 * _/__/ 10 * 11 * Haptic (that is, force feedback) routines for Allegro. 12 * By Beoran (beoran@gmail.com), 2013. 13 * 14 * See readme.txt for copyright information. 15 */ 16 17#ifndef __al_included_allegro5_haptic_h 18#define __al_included_allegro5_haptic_h 19 20#include "allegro5/base.h" 21#include "allegro5/events.h" 22#include "allegro5/mouse.h" 23#include "allegro5/joystick.h" 24 25#ifdef __cplusplus 26 extern "C" { 27#endif 28 29/* Enum: ALLEGRO_HAPTIC_CONSTANTS 30 */ 31enum ALLEGRO_HAPTIC_CONSTANTS { 32 ALLEGRO_HAPTIC_RUMBLE = 1 << 0, 33 ALLEGRO_HAPTIC_PERIODIC = 1 << 1, 34 ALLEGRO_HAPTIC_CONSTANT = 1 << 2, 35 ALLEGRO_HAPTIC_SPRING = 1 << 3, 36 ALLEGRO_HAPTIC_FRICTION = 1 << 4, 37 ALLEGRO_HAPTIC_DAMPER = 1 << 5, 38 ALLEGRO_HAPTIC_INERTIA = 1 << 6, 39 ALLEGRO_HAPTIC_RAMP = 1 << 7, 40 ALLEGRO_HAPTIC_SQUARE = 1 << 8, 41 ALLEGRO_HAPTIC_TRIANGLE = 1 << 9, 42 ALLEGRO_HAPTIC_SINE = 1 << 10, 43 ALLEGRO_HAPTIC_SAW_UP = 1 << 11, 44 ALLEGRO_HAPTIC_SAW_DOWN = 1 << 12, 45 ALLEGRO_HAPTIC_CUSTOM = 1 << 13, 46 ALLEGRO_HAPTIC_GAIN = 1 << 14, 47 ALLEGRO_HAPTIC_ANGLE = 1 << 15, 48 ALLEGRO_HAPTIC_RADIUS = 1 << 16, 49 ALLEGRO_HAPRIC_AZIMUTH = 1 << 17, 50}; 51 52 53 54/* Type: ALLEGRO_HAPTIC 55 */ 56typedef struct ALLEGRO_HAPTIC ALLEGRO_HAPTIC; 57 58/* Direction of a haptic effect. Angle is a value between 0 and 2*M_PI. 59 * An angle 0 means oriented towards the user, M_PI is away from the user 60 * (towards the screen). Angle is only supported if the device capabilities include 61 * ALLEGRO_HAPTIC_ANGLE. 62 * Radius (if supported ) is the distance of the effect from the user 63 * as a value between 0 and 1. Normally it is 0. Radius is only supported if the 64 * device capabilities include ALLEGRO_HAPTIC_RADIUS . 65 * Azimuth is the angle of elevation, between -M_PI and M_PI. 0 points to the 66 * horizontal plane, -M_PI points down, and M_PI points up. 67 * Azimuth is only supported if the device capabilities include 68 * ALLEGRO_HAPTIC_AZIMUTH. 69 * 70 */ 71struct ALLEGRO_HAPTIC_DIRECTION { 72 double angle; 73 double radius; 74 double azimuth; 75}; 76 77/* In all of the following structs, the doubles that express duration represent 78 * time in seconds. The double that represent levels of intensity are between 0.0 79 * and 1.0 that mean no effect and full 100% effect. */ 80 81/* Delay to start the replay and duration of the replay, expressed in seconds. */ 82struct ALLEGRO_HAPTIC_REPLAY { 83 double length; 84 double delay; 85}; 86 87/* Envelope of the effect. */ 88struct ALLEGRO_HAPTIC_ENVELOPE { 89 double attack_length; 90 double attack_level; 91 double fade_length; 92 double fade_level; 93}; 94 95/* Constant effect. Level is between 0.0 and 1.0. */ 96struct ALLEGRO_HAPTIC_CONSTANT_EFFECT { 97 double level; 98 struct ALLEGRO_HAPTIC_ENVELOPE envelope; 99}; 100 101/* Ramp effect. Both start_level and end level are between 0.0 and 1.0. */ 102struct ALLEGRO_HAPTIC_RAMP_EFFECT { 103 double start_level; 104 double end_level; 105 struct ALLEGRO_HAPTIC_ENVELOPE envelope; 106}; 107 108/* Condition effect. */ 109struct ALLEGRO_HAPTIC_CONDITION_EFFECT { 110 double right_saturation; 111 double left_saturation; 112 double right_coeff; 113 double left_coeff; 114 double deadband; 115 double center; 116}; 117 118/* Periodic (wave) effect. */ 119struct ALLEGRO_HAPTIC_PERIODIC_EFFECT { 120 int waveform; 121 double period; 122 double magnitude; 123 double offset; 124 double phase; 125 126 struct ALLEGRO_HAPTIC_ENVELOPE envelope; 127 int custom_len; 128 double *custom_data; 129}; 130 131/* Simple rumble effect with a magnitude between 0.0 and 1.0 for both 132 the strong and the weak rumble motors in the haptic device. */ 133struct ALLEGRO_HAPTIC_RUMBLE_EFFECT { 134 double strong_magnitude; 135 double weak_magnitude; 136}; 137 138union ALLEGRO_HAPTIC_EFFECT_UNION { 139 struct ALLEGRO_HAPTIC_CONSTANT_EFFECT constant; 140 struct ALLEGRO_HAPTIC_RAMP_EFFECT ramp; 141 struct ALLEGRO_HAPTIC_PERIODIC_EFFECT periodic; 142 struct ALLEGRO_HAPTIC_CONDITION_EFFECT condition; 143 struct ALLEGRO_HAPTIC_RUMBLE_EFFECT rumble; 144}; 145 146/* Type: ALLEGRO_HAPTIC_EFFECT. This neeeds to be filled in and uploaded to 147 * the haptic device before it can be played back. 148 */ 149struct ALLEGRO_HAPTIC_EFFECT { 150 int type; 151 int id; 152 struct ALLEGRO_HAPTIC_DIRECTION direction; 153 struct ALLEGRO_HAPTIC_REPLAY replay; 154 union ALLEGRO_HAPTIC_EFFECT_UNION data; 155}; 156 157 158/* Type: ALLEGRO_HAPTIC_EFFECT 159 */ 160typedef struct ALLEGRO_HAPTIC_EFFECT ALLEGRO_HAPTIC_EFFECT; 161 162 163 164/* Type: ALLEGRO_HAPTIC_EFFECT_ID 165 */ 166typedef struct ALLEGRO_HAPTIC_EFFECT_ID ALLEGRO_HAPTIC_EFFECT_ID; 167 168struct ALLEGRO_HAPTIC_EFFECT_ID { 169 ALLEGRO_HAPTIC * _haptic; 170 int _id; 171}; 172 173 174 175/* Installs the haptic (force feedback) device subsystem. */ 176AL_FUNC(bool, al_install_haptic , (void)); 177/* Uninstalls the haptic device subsystem. */ 178AL_FUNC(void, al_uninstall_haptic , (void)); 179/* Returns true if the haptic device subsystem is installed, false if not. */ 180AL_FUNC(bool, al_is_haptic_installed , (void)); 181 182/* Returns true if the mouse has haptic capabilities, false if not.*/ 183AL_FUNC(bool, al_is_mouse_haptic , (ALLEGRO_MOUSE *)); 184/* Returns true if the joystick has haptic capabilities, false if not.*/ 185AL_FUNC(bool, al_is_joystick_haptic , (ALLEGRO_JOYSTICK *)); 186/* Returns true if the keyboard has haptic capabilities, false if not.*/ 187AL_FUNC(bool, al_is_keyboard_haptic , (ALLEGRO_KEYBOARD *)); 188/* Returns true if the display has haptic capabilities, false if not.*/ 189AL_FUNC(bool, al_is_display_haptic , (ALLEGRO_DISPLAY *)); 190/* Returns true if the touch input has haptic capabilities, false if not.*/ 191AL_FUNC(bool, al_is_touch_input_haptic , (ALLEGRO_TOUCH_INPUT *)); 192 193 194/* If the mouse has haptic capabilities, returns the associated haptic device handle. 195 * Otherwise returns NULL. */ 196AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_mouse , (ALLEGRO_MOUSE *)); 197/* If the mouse has haptic capabilities, returns the associated haptic device handle. 198 * Otherwise returns NULL. */ 199AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_joystick , (ALLEGRO_JOYSTICK *)); 200/* If the keyboard has haptic capabilities, returns the associated haptic device handle. 201 * Otherwise returns NULL. */ 202AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_keyboard , (ALLEGRO_DISPLAY *)); 203/* If the display has haptic capabilities, returns the associated haptic device handle. 204 * Otherwise returns NULL. */ 205AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_display , (ALLEGRO_DISPLAY *)); 206/* If the touch input has haptic capabilities, returns the associated haptic 207 * device handle. Otherwise returns NULL. */ 208AL_FUNC(ALLEGRO_HAPTIC *, al_get_haptic_from_touch_input, (ALLEGRO_TOUCH_INPUT *)); 209 210 211 212 213/* Returns true if the haptic device can currently be used, false if not.*/ 214AL_FUNC(bool, al_get_haptic_active , (ALLEGRO_HAPTIC *)); 215 216/* Returns an integer with or'ed values from ALLEGRO_HAPTIC_CONSTANTS, that if 217 set indicate that the haptic device supports the given feature. */ 218AL_FUNC(int, al_get_haptic_capabilities , (ALLEGRO_HAPTIC *)); 219 220/* Sets the gain of the haptic device if supported. Gain is much like volume for sound, 221 it is as if every effect's intensity is multiplied by it. Gain is a value between 222 0.0 and 1.0. Returns true if set sucessfully, false if not.*/ 223AL_FUNC(bool, al_set_haptic_gain , (ALLEGRO_HAPTIC *, double gain)); 224/* Returns the current gain of the device. */ 225AL_FUNC(double, al_get_haptic_gain , (ALLEGRO_HAPTIC *)); 226 227 228/* Returns the maximum amount of haptic effects that can be uploaded to the device. */ 229AL_FUNC(int, al_get_num_haptic_effects , (ALLEGRO_HAPTIC *)); 230 231/* Returns true if the haptic device can play the haptic effect as given, false if not. */ 232AL_FUNC(bool, al_is_haptic_effect_ok , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *)); 233 234/* Uploads the haptic effect to the device. In play_id, a handle is stored that is 235 a reference to be used to control playback of the effect. */ 236AL_FUNC(bool, al_upload_haptic_effect , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, ALLEGRO_HAPTIC_EFFECT_ID * play_id)); 237 238/* Plays back a previously uploaded haptic effect. */ 239AL_FUNC(bool, al_play_haptic_effect , (ALLEGRO_HAPTIC_EFFECT_ID *, int loop)); 240 241/* Uploads and immediately plays back the haptic effect to the device. */ 242AL_FUNC(bool, al_upload_and_play_haptic_effect , (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, int loop, ALLEGRO_HAPTIC_EFFECT_ID * play_id)); 243 244/* Stops playing a haptic effect . */ 245AL_FUNC(bool, al_stop_haptic_effect , (ALLEGRO_HAPTIC_EFFECT_ID *)); 246/* Stops playing all haptic effects on this device. */ 247AL_FUNC(bool, al_stop_all_haptic_effects , (ALLEGRO_HAPTIC *)); 248 249/* Returns true if the haptic effect is playing or false if not or if stopped. */ 250AL_FUNC(bool, al_is_haptic_effect_playing, (ALLEGRO_HAPTIC_EFFECT_ID *)); 251 252/* Uploads a simple rumble effect to the haptic device and starts playback immediately. 253 */ 254AL_FUNC(bool, al_rumble_haptic, (ALLEGRO_HAPTIC *, ALLEGRO_HAPTIC_EFFECT *, double intensity, ALLEGRO_HAPTIC_EFFECT_ID *));

Edit 2: I checked the X Windows mouse, display, and keyboard drivers, and the problem with them is that there is not trace to befound of the the underlying /dev/input/eventXX device. So there's no easy way to enable haptic support for them if any. The Linux joystick driver does have a fd of the input device that can be used to send haptic effects to, but all in all, it seems that the API I propose above could only be implemented relatively easily on on Linux for joysticks. For all other devices we'd have to scan all input devices and try to match them with the corresponding X Windows input... That seems convoluted. :/

Peter Wang
Member #23
April 2000

We never access the underlying device files, as ostensibly X is still a network aware system, and keyboard and mouse could be on another machine. So we would probably wait the necessary support appears in X, or whatever replaces it.

(We could actually support joystick via XInput, but AFAIK no one really does so.)

beoran
Member #12,636
March 2011

OK, that's fair enough. I can live with the idea that on X, we'll only have haptic joysticks for the time being, and then only on Linux. In theory SDL 2 is more capable than this, but I can see in practice, the API above will suffice for a first implemenation of haptics on Allegro. GLFW, for example also has a similar limitation of haptics only for joysticks. On other platforms, non-joystick haptics (like Vibrate on Android) may still be defined using al_get_haptic_from_display, etc.

With the current driver joystick support on other *BSD/*nix systems does not work anyway. And I've been reading around a bit and it looks like on Linux we'll probably have also to support either Wayland or Mir, or both (or maybe nether and system nr 3 will come along). Those systems just boil down that we'll have to use /dev/input/eventXX for everything input related anyway. When that happens, we can enable haptic support for all these devices.

I'll start implementing the API above for Linux. I will have to refactor the Linux joystick driver a bit though since now the haptic driver will need to read the joysticks driver's internal details. Probably the same will be needed on other platforms too. But that's not a fundamental problem.

 1   2 


Go to: