Controllers.md 4.5 KB

Controllers

This guide will teach you how to interact with tracked motion controllers. Controllers are an important source of user input in VR experiences. We'll learn how to draw models for controllers, figure out when a button on the controller is pressed, and even trigger haptic feedback!

Discovering Controllers

The VR functionality in LÖVR is all in the lovr.headset module. To get the number of connected controllers, use lovr.headset.getControllerCount.

function lovr.load()
  print(lovr.headset.getControllerCount())
end

There are two callbacks related to Controllers: lovr.controlleradded and lovr.controllerremoved. Using them, you can determine when controllers are connected and disconnected:

function lovr.controlleradded(controller)
  print('Now there are ' .. lovr.headset.getControllerCount() .. ' controllers.')
end

function lovr.controllerremoved(controller)
  print('Now there are ' .. lovr.headset.getControllerCount() .. ' controllers.')
end

Often, controllers need to be moved around a bit for them to be recognized, so make sure you add code in those callbacks to keep your list of controllers up to date.

To get a list of currently connected controllers, use lovr.headset.getControllers. We'll be using that more in a bit.

Position and Orientation

To retrieve the position of a controller, use Controller:getPosition:

controllers = lovr.headset.getControllers()
for i, controller in ipairs(controllers) do
  print(controller:getPosition())
end

The ipairs function returns an iterator that can be used in a for loop. This lets you run a chunk of code on each item in a list. Here, we're printing out the position of each controller.

Similarly, you can get the orientation of a controller (in angle-axis representation) using Controller:getOrientation. We can combine these two functions to draw cubes at the position of the player's hands:

function lovr.draw()
  controllers = lovr.headset.getControllers()
  x, y, z = controller:getPosition()
  angle, ax, ay, az = controller:getOrientation()
  lovr.graphics.cube('line', x, y, z, .2, angle, ax, ay, az)
end

Let's replace that cube with a realistic model of the controller.

Controller Models

We can create a new Model object for a controller with Controller:newModel. The model will automatically have a texture applied. Drawing the model with the position and orientation of the controller object greatly increases the feeling of presence of an application. Here's an example that keeps track of the list of controllers and draws their models:

function refreshControllers()
  controllers = lovr.headset.getControllers()
  controllerModels = {}
  for i, controller in ipairs(controllers) do
    controllerModels[i] = controller:newModel()
  end
end

function lovr.load()
  refreshControllers()
end

function lovr.controlleradded()
  refreshControllers()
end

function lovr.controllerremoved()
  refreshControllers()
end

function lovr.draw()
  for i, controller in ipairs(controllers) do
    x, y, z = controller:getPosition()
    angle, ax, ay, az = controller:getOrientation()
    controllerModels[i]:draw(x, y, z, 1, angle, ax, ay, az)
  end
end

Controller Input

To determine if a button on the controller is pressed, use Controller:isDown:

print(controller:isDown('menu'))

The first parameter is a string with the name of a button, which can be system, menu, grip, or touchpad. The return value is a "boolean": either true or false depending on whether or not the button is pressed.

You can also retrieve the input state of axes. Axes are inputs that can take on a continuous value between 0 and 1. Axis state can be retrieved using Controller:getAxis. Available axes are trigger, touchx, and touchy.

Haptics

You can trigger haptic feedback on controllers to make them vibrate! To do this, use Controller:vibrate. The function takes in a number representing how long the controller should vibrate for, in seconds. Currently, Vive controllers can only vibrate for durations less than .004 seconds. To create longer or stronger vibrations, call the function over a period of several frames.

function lovr.update(dt)
  if controller:getAxis('trigger') == 1 then
    controller:vibrate(.002)
  end
end

That's all for controllers. The next guide is about Sound.