Game Development Community

dev|Pro Game Development Curriculum

Leap Motion for T3D

by Entr0py · 01/18/2013 (8:42 am) · 5 comments

This will get your leap motion data into T3d. It doesn't do much but spam the console right now, but this should get you started in the right direction. You will have to alter LeapListener::onFrame to pass the data to wherever it is you need it.

LeapListener::onFrame is called every time the Leap device creates a new frame. You may want to change this to only call a leap data frame when your frames are rendered in which case you will have to poll the controller object (controller.frame()) rather than use the LeapListener::onFrame function.


First you need to add the leap SDK libs and includes to your project. You can get them at leapmotion.com in the developer's section.

Here is my header file:
#include <iostream>

#ifndef _WINLEAPINPUT_H_
#define _WINLEAPINPUT_H_

#ifndef _LEAP_H_ 
#include "leap.h"
#endif
#ifndef _SIMBASE_H_
#include "console/simBase.h"
#endif
#ifndef _PLATFORMTHREAD_H_  
    #include "platform/threads/thread.h"  
#endif  

class LeapListener : public Leap::Listener {
  public:
public:  
    LeapListener();  
    ~LeapListener();  

    virtual void onInit(const Leap::Controller&);
    virtual void onConnect(const Leap::Controller&);
    virtual void onDisconnect(const Leap::Controller&);
    virtual void onExit(const Leap::Controller&);
    virtual void onFrame(const Leap::Controller&);
};

class LeapThread : public SimObject  
{  
    typedef SimObject Parent;  
  
public:  
    LeapThread();  
    ~LeapThread();  
  
    Thread* mThread;  
    static void launchThread(void* data);  
	Leap::Frame getframe(int history);

	LeapListener listener;
	Leap::Controller controller;

    void processThread();  
      
    DECLARE_CONOBJECT(LeapThread);  
      
};  

#endif

And my cpp file:
#include "platformWin32/winLeapInput.h"
#include "console/console.h"
#include "console/engineAPI.h"
#include "console/consoleTypes.h"   
#include "console/simBase.h" 

LeapListener::LeapListener()  
{ 
}

void LeapListener::onInit(const Leap::Controller& controller) {
  Con::printf("Leap Motion Listener Initialized");
}

void LeapListener::onConnect(const Leap::Controller& controller) {
    Con::printf("Leap Motion Connected");
}

void LeapListener::onDisconnect(const Leap::Controller& controller) {
    Con::printf("Leap Motion Disconnected");
}

void LeapListener::onExit(const Leap::Controller& controller) {
    Con::printf("Leap Motion Exited");
}

void LeapListener::onFrame(const Leap::Controller& controller) {
  // Get the most recent frame and report some basic information
  const Leap::Frame frame = controller.frame();

  if(controller.isConnected())
	Con::executef("onLeapFrame");

Con::printf("Leap Motion Frame Id: %d, time: %d", frame.id()), frame.timestamp();
Con::printf("Tools: %d", frame.tools().count());

  if (!frame.hands().empty()) {
    // Get the first hand
    const Leap::Hand hand = frame.hands()[0];

    // Check if the hand has any fingers
    const Leap::FingerList fingers = hand.fingers();
    if (!fingers.empty()) {
      // Calculate the hand's average finger tip position
      Leap::Vector avgPos;
      for (int i = 0; i < fingers.count(); ++i) {
        avgPos += fingers[i].tipPosition();
      }
      avgPos /= (float)fingers.count();
	  Con::printf("Fingers %d , Average Finger Pos: %s ", fingers.count(), avgPos.toString().c_str());
    }
	Con::printf("Hands: %d", frame.hands().count());
    // Get the hand's sphere radius and palm position
	Con::printf("Hand sphere radius: %f",hand.sphereRadius());
 	Con::printf("Hand palm position: %f",hand.palmPosition().toString().c_str());

    // Get the hand's normal vector and direction
    const Leap::Vector normal = hand.palmNormal();
    const Leap::Vector direction = hand.direction();

	// Calculate the hand's pitch, roll, and yaw angles
	Con::printf("Hand Pitch: %f ", direction.pitch() * Leap::RAD_TO_DEG);
	Con::printf("Hand Rolls: %f ", normal.roll() * Leap::RAD_TO_DEG);
	Con::printf("Hand Yaw: %f ", direction.yaw() * Leap::RAD_TO_DEG);
  }
}

LeapListener::~LeapListener()  
{ 
}

IMPLEMENT_CONOBJECT(LeapThread);  
  
LeapThread::LeapThread()  
{  
    mThread = new Thread((ThreadRunFunction)launchThread, this);      
    mThread->start();  
}  
  
LeapThread::~LeapThread()  
{  
	// needs a proper destruction

	if(mThread)   
		delete mThread;  

    mThread = NULL;  
}  
  
void LeapThread::launchThread(void* data)  
{  
    LeapThread* pThis = (LeapThread*)data;  

    pThis->processThread();    
}  
  
void LeapThread::processThread()  
{  
	controller.addListener(listener);
}

In script somewhere:
function onLeapFrame()
{
   // do stuff here if you want
}

$leap = new leapthread();
Bugs:
This code needs proper destruction of the listener/controller because it hangs the client when it is closed.

#1
01/18/2013 (10:58 am)
oh, nice to see others working with it already :)

-applied for their devkit for a project idea I have, and eagerly await feedback atm!
#2
01/18/2013 (11:07 am)
The next version of T3D will support the Leap Motion (among other devices) with it's new input manager.
#3
01/18/2013 (11:12 am)
Great! I would like to see a demo of a pair of hands that can work with Physx objects.
#4
01/24/2013 (1:23 pm)
Blog talking about Leap Motion controller support in Torque 3D, and a demo game you can try out: www.garagegames.com/community/blogs/view/22128

- Dave
#5
01/24/2013 (3:10 pm)
Awesome thanks!