<div dir="ltr"><div><br></div><div>Lucas and I have been working on VTK's VR support and one issue we bumped into was event handing. VTK's event handling tends to be data light where most events follow this approach</div><div><br></div><div>1) event happens</div><div><br></div><div>2) we set properties on the interactor such as alt/shift/control key state, mouse position, etc</div><div><br></div><div>3) fire the event (with little or no calldata)</div><div><br></div><div>4) event handlers query needed properties from the interactor</div><div><br></div><div>The challenge here is that as more event types are supported, the interactor's state and structure is required to grow to match them.  For example with multitouch events, the interactor now has to support multiple mouse positions and pointer indexes. Now add in multi controller VR and we have to also store arrays of world coordinate positions and orientations and what controller the current event corresponds to.</div><div><br></div><div>Many systems use a different approach where they define an event data structure or class that get passed with the event (or associated with the event). Then whatever is handling the event receives that data structure which contains most of the key properties of the event.  Such an event structure can also be used for filtering. For example currently in VTK you can map keyboard events on a widget using the vtkWidgetCallbackMapper method</div><div><br></div><div><div>void SetCallbackMethod(unsigned long VTKEvent, int modifiers, char keyCode,</div><div>                         int repeatCount, const char* keySym,</div><div>                         unsigned long widgetEvent,</div><div>                         vtkAbstractWidget *w, CallbackType f);</div></div><div><br></div><div>Note that this signature is designed for keyboard events as it contains keyboard event specific parameters. To add a mapping for multitouch, or VR controller events would require more event specific signatures. In contrast if we had a formal vtkEventData structure then the method could use a vtkEventData as a filter and handle many different event types as long as the EventData has an equality operator on it (or maybe a filtering specific equality).</div><div><br></div><div>Lucas and I have tried this out for VR and it has made event handling reasonable and fairly clean and I would like to get some feedback on the idea/approach/etc.  Right now our vtkEventData is included below. It uses the approach of a union of event type structs and what has been fleshed out is targeted at VR but it should be easy to see how keyboard or mouse devices/events could get added as well.</div><div><br></div><div>Thanks!</div><div>Ken</div><div><br></div><div><br></div><div><br></div><div><div>enum class vtkEventDataDevice {</div><div>  Unknown = -1,</div><div>  HeadMountedDisplay,</div><div>  RightController,</div><div>  LeftController,</div><div>  NumberOfDevices</div><div>};</div><div><br></div><div>const int vtkEventDataNumberOfDevices =</div><div>  static_cast<int>(vtkEventDataDevice::NumberOfDevices);</div><div><br></div><div>enum class vtkEventDataDeviceInput {</div><div>  Unknown = -1,</div><div>  Trigger,</div><div>  TrackPad,</div><div>  Grip,</div><div>  ApplicationMenu,</div><div>  NumberOfInputs</div><div>};</div><div><br></div><div>const int vtkEventDataNumberOfInputs =</div><div>  static_cast<int>(vtkEventDataDeviceInput::NumberOfInputs);</div><div><br></div><div>enum class vtkEventDataAction {</div><div>  Unknown = -1,</div><div>  Press,</div><div>  Release,</div><div>  NumberOfActions</div><div>};</div><div><br></div><div>struct vtkEventDataButton3D</div><div>{</div><div>  vtkEventDataDevice Device;</div><div>  vtkEventDataDeviceInput Input;</div><div>  vtkEventDataAction Action;</div><div>  double WorldPosition[3];</div><div>  double WorldOrientation[4];</div><div><br></div><div>  bool operator==(const vtkEventDataButton3D& rh)</div><div>  {</div><div>    return (Device == rh.Device && Input == rh.Input && Action == rh.Action);</div><div>  }</div><div>  void SetWorldPosition(const double p[3])</div><div>  {</div><div>    WorldPosition[0] = p[0];</div><div>    WorldPosition[1] = p[1];</div><div>    WorldPosition[2] = p[2];</div><div>  }</div><div>  void SetWorldOrientation(const double p[4])</div><div>  {</div><div>    WorldOrientation[0] = p[0];</div><div>    WorldOrientation[1] = p[1];</div><div>    WorldOrientation[2] = p[2];</div><div>    WorldOrientation[3] = p[3];</div><div>  }</div><div>};</div><div><br></div><div>struct vtkEventDataMove3D</div><div>{</div><div>  vtkEventDataDevice Device;</div><div>  double WorldPosition[3];</div><div>  double WorldOrientation[4];</div><div><br></div><div>  bool operator==(const vtkEventDataMove3D& rh)</div><div>  {</div><div>    return (Device == rh.Device);</div><div>  }</div><div>  void SetWorldPosition(const double p[3])</div><div>  {</div><div>    WorldPosition[0] = p[0];</div><div>    WorldPosition[1] = p[1];</div><div>    WorldPosition[2] = p[2];</div><div>  }</div><div>  void SetWorldOrientation(const double p[4])</div><div>  {</div><div>    WorldOrientation[0] = p[0];</div><div>    WorldOrientation[1] = p[1];</div><div>    WorldOrientation[2] = p[2];</div><div>    WorldOrientation[3] = p[3];</div><div>  }</div><div>};</div><div><br></div><div>typedef union</div><div>{</div><div>  vtkEventDataButton3D Button;</div><div>  vtkEventDataMove3D Move;</div><div>} vtkEventDataUnion;</div><div><br></div><div>struct vtkEventData</div><div>{</div><div>  int Type; // see vtkCommand.h</div><div>  vtkEventDataUnion Data;</div><div><br></div><div>  bool operator==(const vtkEventData& rh)</div><div>  {</div><div>    if (Type != rh.Type)</div><div>    {</div><div>      return false;</div><div>    }</div><div>    switch (Type)</div><div>    {</div><div>      case vtkCommand::ButtonEvent3D:</div><div>        return Data.Button == rh.Data.Button;</div><div>      case vtkCommand::MoveEvent3D:</div><div>        return Data.Move == rh.Data.Move;</div><div>    }</div><div>    return false;</div><div>  }</div><div><br></div><div>  bool GetDevice(vtkEventDataDevice &val)</div><div>  {</div><div>    switch (Type)</div><div>    {</div><div>      case vtkCommand::ButtonEvent3D:</div><div>        val = Data.Button.Device;</div><div>        return true;</div><div>      case vtkCommand::MoveEvent3D:</div><div>        val = Data.Move.Device;</div><div>        return true;</div><div>    }</div><div>    return false;</div><div>  }</div><div><br></div><div>  bool GetWorldPosition(double *&pos)</div><div>  {</div><div>    switch (Type)</div><div>    {</div><div>      case vtkCommand::ButtonEvent3D:</div><div>        pos = Data.Button.WorldPosition;</div><div>        return true;</div><div>      case vtkCommand::MoveEvent3D:</div><div>        pos = Data.Move.WorldPosition;</div><div>        return true;</div><div>    }</div><div>    return false;</div><div>  }</div><div><br></div><div>  bool GetWorldOrientation(double *&val)</div><div>  {</div><div>    switch (Type)</div><div>    {</div><div>      case vtkCommand::ButtonEvent3D:</div><div>        val = Data.Button.WorldOrientation;</div><div>        return true;</div><div>      case vtkCommand::MoveEvent3D:</div><div>        val = Data.Move.WorldOrientation;</div><div>        return true;</div><div>    }</div><div>    return false;</div><div>  }</div><div>};</div></div><div><br></div><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div>Ken Martin PhD<div>Distinguished Engineer<br><span style="font-size:12.8px">Kitware Inc.</span><br></div><div>28 Corporate Drive<br>Clifton Park NY 12065<br><div><br></div><div><span style="font-size:10pt;font-family:Tahoma,sans-serif">This communication,
including all attachments, contains confidential and legally privileged
information, and it is intended only for the use of the addressee.  Access to this email by anyone else is
unauthorized. If you are not the intended recipient, any disclosure, copying,
distribution or any action taken in reliance on it is prohibited and may be
unlawful. If you received this communication in error please notify us
immediately and destroy the original message. 
Thank you.</span></div></div></div></div></div>
</div>