mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Leap Motion input device support
This commit is contained in:
parent
ecb592b908
commit
6105849df2
|
|
@ -0,0 +1,34 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LEAPMOTIONCONSTANTS_H_
|
||||
#define _LEAPMOTIONCONSTANTS_H_
|
||||
|
||||
namespace LeapMotionConstants
|
||||
{
|
||||
enum Constants {
|
||||
MaxHands = 2,
|
||||
MaxPointablesPerHand = 5,
|
||||
};
|
||||
}
|
||||
|
||||
#endif // _LEAPMOTIONCONSTANTS_H_
|
||||
353
Engine/source/platform/input/leapMotion/leapMotionData.cpp
Normal file
353
Engine/source/platform/input/leapMotion/leapMotionData.cpp
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/input/leapMotion/leapMotionData.h"
|
||||
#include "platform/input/leapMotion/leapMotionUtil.h"
|
||||
|
||||
LeapMotionDeviceData::LeapMotionDeviceData()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void LeapMotionDeviceData::reset()
|
||||
{
|
||||
mDataSet = false;
|
||||
|
||||
mIsValid = false;
|
||||
|
||||
mHasTrackingData = false;
|
||||
|
||||
for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
|
||||
{
|
||||
mHandValid[i] = false;
|
||||
|
||||
for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
|
||||
{
|
||||
mPointableValid[i][j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionDeviceData::setData(const Leap::Frame& frame, LeapMotionDeviceData* prevData, bool keepHandIndexPersistent, bool keepPointableIndexPersistent, const F32& maxHandAxisRadius)
|
||||
{
|
||||
mIsValid = frame.isValid();
|
||||
if(!mIsValid)
|
||||
return;
|
||||
|
||||
// Determine if there is any valid tracking data
|
||||
mHasTrackingData = frame.hands().count() > 0 || frame.pointables().count() > 0;
|
||||
|
||||
const Leap::HandList hands = frame.hands();
|
||||
|
||||
// Check if the hand index needs to persist between frames, but only if the
|
||||
// previous data is valid
|
||||
if(keepHandIndexPersistent && prevData && prevData->mDataSet && prevData->mIsValid)
|
||||
{
|
||||
processPersistentHands(frame.hands(), keepPointableIndexPersistent, prevData);
|
||||
}
|
||||
else
|
||||
{
|
||||
processHands(frame.hands());
|
||||
}
|
||||
|
||||
// Single hand rotation as axis
|
||||
if(mHandValid[0])
|
||||
{
|
||||
Point2F axis;
|
||||
LeapMotionUtil::calculateHandAxisRotation(mHandRot[0], maxHandAxisRadius, axis);
|
||||
|
||||
mHandRotAxis[0] = axis.x;
|
||||
mHandRotAxis[1] = axis.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The first hand is not valid so we reset the axis rotation to none
|
||||
mHandRotAxis[0] = 0.0f;
|
||||
mHandRotAxis[1] = 0.0f;
|
||||
}
|
||||
|
||||
// Store the current sequence number
|
||||
mSequenceNum = frame.id();
|
||||
|
||||
mDataSet = true;
|
||||
}
|
||||
|
||||
void LeapMotionDeviceData::processPersistentHands(const Leap::HandList& hands, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData)
|
||||
{
|
||||
S32 numHands = hands.count();
|
||||
|
||||
static S32 handDataIndex[LeapMotionConstants::MaxHands];
|
||||
static bool handIndexUsed[LeapMotionConstants::MaxHands];
|
||||
static Vector<S32> frameHandFound;
|
||||
|
||||
// Clear out our lookup arrays
|
||||
for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
|
||||
{
|
||||
handDataIndex[i] = -1;
|
||||
handIndexUsed[i] = false;
|
||||
}
|
||||
frameHandFound.setSize(numHands);
|
||||
for(U32 i=0; i<numHands; ++i)
|
||||
{
|
||||
frameHandFound[i] = -1;
|
||||
}
|
||||
|
||||
// Check if any hands this frame were picked up last frame
|
||||
for(U32 i=0; i<numHands; ++i)
|
||||
{
|
||||
const Leap::Hand& hand = hands[i];
|
||||
for(U32 j=0; j<LeapMotionConstants::MaxHands; ++j)
|
||||
{
|
||||
if(prevData && prevData->mHandValid[j] && hand.id() == prevData->mHandID[j])
|
||||
{
|
||||
handDataIndex[j] = i;
|
||||
frameHandFound[i] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process all hands that were present in the last frame
|
||||
for(U32 i=0; i<numHands; ++i)
|
||||
{
|
||||
if(frameHandFound[i] != -1)
|
||||
{
|
||||
processHand(hands[i], frameHandFound[i], keepPointableIndexPersistent, prevData);
|
||||
handIndexUsed[frameHandFound[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process all hands that were not present in the last frame
|
||||
for(U32 i=0; i<numHands; ++i)
|
||||
{
|
||||
if(frameHandFound[i] != -1)
|
||||
continue;
|
||||
|
||||
// Find the first hand data that has not yet been used
|
||||
for(U32 j=0; j<LeapMotionConstants::MaxHands; ++j)
|
||||
{
|
||||
if(!handIndexUsed[j])
|
||||
{
|
||||
// Process this hand
|
||||
processHand(hands[i], j, keepPointableIndexPersistent, prevData);
|
||||
handIndexUsed[j] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, mark all hand data that has not been processed this frame as invalid
|
||||
for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
|
||||
{
|
||||
if(!handIndexUsed[i])
|
||||
{
|
||||
mHandValid[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionDeviceData::processHands(const Leap::HandList& hands)
|
||||
{
|
||||
S32 numHands = hands.count();
|
||||
|
||||
// Process all valid hands
|
||||
S32 handsToProcess = getMin(numHands, LeapMotionConstants::MaxHands);
|
||||
for(U32 i=0; i<handsToProcess; ++i)
|
||||
{
|
||||
processHand(hands[i], i, false, NULL);
|
||||
}
|
||||
|
||||
// Take care of any hands that do not exist this frame
|
||||
for(U32 i=handsToProcess; i<LeapMotionConstants::MaxHands; ++i)
|
||||
{
|
||||
mHandValid[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionDeviceData::processHand(const Leap::Hand& hand, U32 handIndex, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData)
|
||||
{
|
||||
mHandValid[handIndex] = true;
|
||||
|
||||
mHandID[handIndex] = hand.id();
|
||||
|
||||
// Set the hand position
|
||||
LeapMotionUtil::convertPosition(hand.palmPosition(), mHandRawPos[handIndex][0], mHandRawPos[handIndex][1], mHandRawPos[handIndex][2]);
|
||||
mHandPos[handIndex][0] = (S32)mFloor(mHandRawPos[handIndex][0]);
|
||||
mHandPos[handIndex][1] = (S32)mFloor(mHandRawPos[handIndex][1]);
|
||||
mHandPos[handIndex][2] = (S32)mFloor(mHandRawPos[handIndex][2]);
|
||||
|
||||
mHandPosPoint[handIndex].set(mHandPos[handIndex][0], mHandPos[handIndex][1], mHandPos[handIndex][2]);
|
||||
|
||||
// Set the hand rotation
|
||||
LeapMotionUtil::convertHandRotation(hand, mHandRot[handIndex]);
|
||||
mHandRotQuat[handIndex].set(mHandRot[handIndex]);
|
||||
|
||||
// Process the pointables associated with this hand
|
||||
if(keepPointableIndexPersistent)
|
||||
{
|
||||
processPersistentHandPointables(hand.pointables(), handIndex, prevData);
|
||||
}
|
||||
else
|
||||
{
|
||||
processHandPointables(hand.pointables(), handIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionDeviceData::processPersistentHandPointables(const Leap::PointableList& pointables, U32 handIndex, LeapMotionDeviceData* prevData)
|
||||
{
|
||||
S32 numPointables = pointables.count();
|
||||
|
||||
static S32 pointableDataIndex[LeapMotionConstants::MaxPointablesPerHand];
|
||||
static bool pointableIndexUsed[LeapMotionConstants::MaxPointablesPerHand];
|
||||
static Vector<S32> framePointableFound;
|
||||
|
||||
// Clear out our lookup arrays
|
||||
for(U32 i=0; i<LeapMotionConstants::MaxPointablesPerHand; ++i)
|
||||
{
|
||||
pointableDataIndex[i] = -1;
|
||||
pointableIndexUsed[i] = false;
|
||||
}
|
||||
framePointableFound.setSize(numPointables);
|
||||
for(U32 i=0; i<numPointables; ++i)
|
||||
{
|
||||
framePointableFound[i] = -1;
|
||||
}
|
||||
|
||||
// Check if any pointables for this hand during this frame were picked
|
||||
// up last frame
|
||||
for(U32 i=0; i<numPointables; ++i)
|
||||
{
|
||||
const Leap::Pointable& pointable = pointables[i];
|
||||
for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
|
||||
{
|
||||
if(prevData && prevData->mPointableValid[handIndex][j] && pointable.id() == prevData->mPointableID[handIndex][j])
|
||||
{
|
||||
pointableDataIndex[j] = i;
|
||||
framePointableFound[i] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process all hand pointables that were present in the last frame
|
||||
for(U32 i=0; i<numPointables; ++i)
|
||||
{
|
||||
if(framePointableFound[i] != -1)
|
||||
{
|
||||
processHandPointable(pointables[i], handIndex, framePointableFound[i]);
|
||||
pointableIndexUsed[framePointableFound[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process all hand pointables that were not present in the last frame
|
||||
for(U32 i=0; i<numPointables; ++i)
|
||||
{
|
||||
if(framePointableFound[i] != -1)
|
||||
continue;
|
||||
|
||||
// Find the first hand pointable data that has not yet been used
|
||||
for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
|
||||
{
|
||||
if(!pointableIndexUsed[j])
|
||||
{
|
||||
// Process the pointable
|
||||
processHandPointable(pointables[i], handIndex, j);
|
||||
pointableIndexUsed[j] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, mark all hand pointable data that has not been process this frame as invalid
|
||||
for(U32 i=0; i<LeapMotionConstants::MaxPointablesPerHand; ++i)
|
||||
{
|
||||
if(!pointableIndexUsed[i])
|
||||
{
|
||||
mPointableValid[handIndex][i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionDeviceData::processHandPointables(const Leap::PointableList& pointables, U32 handIndex)
|
||||
{
|
||||
// Process all pointables attached to the hand
|
||||
S32 numPointables = pointables.count();
|
||||
S32 pointablesToProcess = getMin(numPointables, LeapMotionConstants::MaxPointablesPerHand);
|
||||
for(U32 i=0; i<pointablesToProcess; ++i)
|
||||
{
|
||||
processHandPointable(pointables[i], handIndex, i);
|
||||
}
|
||||
|
||||
// Take care of any pointables that do not exist this frame
|
||||
for(U32 i=pointablesToProcess; i<LeapMotionConstants::MaxPointablesPerHand; ++i)
|
||||
{
|
||||
mPointableValid[handIndex][i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionDeviceData::processHandPointable(const Leap::Pointable& pointable, U32 handIndex, U32 handPointableIndex)
|
||||
{
|
||||
mPointableValid[handIndex][handPointableIndex] = true;
|
||||
|
||||
mPointableID[handIndex][handPointableIndex] = pointable.id();
|
||||
mPointableLength[handIndex][handPointableIndex] = pointable.length();
|
||||
mPointableWidth[handIndex][handPointableIndex] = pointable.width();
|
||||
|
||||
// Set the pointable position
|
||||
LeapMotionUtil::convertPosition(pointable.tipPosition(), mPointableRawPos[handIndex][handPointableIndex][0], mPointableRawPos[handIndex][handPointableIndex][1], mPointableRawPos[handIndex][handPointableIndex][2]);
|
||||
mPointablePos[handIndex][handPointableIndex][0] = (S32)mFloor(mPointableRawPos[handIndex][handPointableIndex][0]);
|
||||
mPointablePos[handIndex][handPointableIndex][1] = (S32)mFloor(mPointableRawPos[handIndex][handPointableIndex][1]);
|
||||
mPointablePos[handIndex][handPointableIndex][2] = (S32)mFloor(mPointableRawPos[handIndex][handPointableIndex][2]);
|
||||
|
||||
mPointablePosPoint[handIndex][handPointableIndex].set(mPointablePos[handIndex][handPointableIndex][0], mPointablePos[handIndex][handPointableIndex][1], mPointablePos[handIndex][handPointableIndex][2]);
|
||||
|
||||
// Set the pointable rotation
|
||||
LeapMotionUtil::convertPointableRotation(pointable, mPointableRot[handIndex][handPointableIndex]);
|
||||
mPointableRotQuat[handIndex][handPointableIndex].set(mPointableRot[handIndex][handPointableIndex]);
|
||||
}
|
||||
|
||||
U32 LeapMotionDeviceData::compare(LeapMotionDeviceData* other)
|
||||
{
|
||||
S32 result = DIFF_NONE;
|
||||
|
||||
// Check hand rotation as axis
|
||||
if(mHandRotAxis[0] != other->mHandRotAxis[0] || !mDataSet)
|
||||
{
|
||||
result |= DIFF_HANDROTAXISX;
|
||||
}
|
||||
if(mHandRotAxis[1] != other->mHandRotAxis[1] || !mDataSet)
|
||||
{
|
||||
result |= DIFF_HANDROTAXISY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
U32 LeapMotionDeviceData::compareMeta(LeapMotionDeviceData* other)
|
||||
{
|
||||
S32 result = DIFF_NONE;
|
||||
|
||||
if(mHasTrackingData != other->mHasTrackingData || !mDataSet)
|
||||
{
|
||||
result |= METADIFF_FRAME_VALID_DATA;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
113
Engine/source/platform/input/leapMotion/leapMotionData.h
Normal file
113
Engine/source/platform/input/leapMotion/leapMotionData.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LEAPMOTIONDATA_H_
|
||||
#define _LEAPMOTIONDATA_H_
|
||||
|
||||
#include "console/consoleTypes.h"
|
||||
#include "math/mMathFn.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "math/mQuat.h"
|
||||
#include "platform/input/leapMotion/leapMotionConstants.h"
|
||||
#include "Leap.h"
|
||||
|
||||
struct LeapMotionDeviceData
|
||||
{
|
||||
enum DataDifferences {
|
||||
DIFF_NONE = 0,
|
||||
DIFF_HANDROTAXISX = (1<<1),
|
||||
DIFF_HANDROTAXISY = (1<<2),
|
||||
|
||||
DIFF_HANDROTAXIS = (DIFF_HANDROTAXISX | DIFF_HANDROTAXISY),
|
||||
};
|
||||
|
||||
enum MetaDataDifferences {
|
||||
METADIFF_NONE = 0,
|
||||
METADIFF_FRAME_VALID_DATA = (1<<0),
|
||||
};
|
||||
|
||||
protected:
|
||||
void processPersistentHands(const Leap::HandList& hands, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData);
|
||||
void processHands(const Leap::HandList& hands);
|
||||
void processHand(const Leap::Hand& hand, U32 handIndex, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData);
|
||||
|
||||
void processPersistentHandPointables(const Leap::PointableList& pointables, U32 handIndex, LeapMotionDeviceData* prevData);
|
||||
void processHandPointables(const Leap::PointableList& pointables, U32 handIndex);
|
||||
void processHandPointable(const Leap::Pointable& pointable, U32 handIndex, U32 handPointableIndex);
|
||||
|
||||
public:
|
||||
bool mDataSet;
|
||||
|
||||
// Frame Data Set
|
||||
bool mIsValid;
|
||||
bool mHasTrackingData;
|
||||
|
||||
// Hand Data Set
|
||||
bool mHandValid[LeapMotionConstants::MaxHands];
|
||||
S32 mHandID[LeapMotionConstants::MaxHands];
|
||||
|
||||
// Hand Position
|
||||
F32 mHandRawPos[LeapMotionConstants::MaxHands][3];
|
||||
S32 mHandPos[LeapMotionConstants::MaxHands][3];
|
||||
Point3F mHandPosPoint[LeapMotionConstants::MaxHands];
|
||||
|
||||
// Hand Rotation
|
||||
MatrixF mHandRot[LeapMotionConstants::MaxHands];
|
||||
QuatF mHandRotQuat[LeapMotionConstants::MaxHands];
|
||||
|
||||
// Hand rotation as axis x, y
|
||||
F32 mHandRotAxis[2];
|
||||
|
||||
// Pointable Data Set
|
||||
bool mPointableValid[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand];
|
||||
S32 mPointableID[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand];
|
||||
F32 mPointableLength[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand];
|
||||
F32 mPointableWidth[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand];
|
||||
|
||||
// Pointable Position
|
||||
F32 mPointableRawPos[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand][3];
|
||||
S32 mPointablePos[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand][3];
|
||||
Point3F mPointablePosPoint[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand];
|
||||
|
||||
// Pointable Rotation
|
||||
MatrixF mPointableRot[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand];
|
||||
QuatF mPointableRotQuat[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand];
|
||||
|
||||
// Sequence number from device
|
||||
U64 mSequenceNum;
|
||||
|
||||
LeapMotionDeviceData();
|
||||
|
||||
/// Reset device data
|
||||
void reset();
|
||||
|
||||
/// Set data based on Leap Motion device data
|
||||
void setData(const Leap::Frame& frame, LeapMotionDeviceData* prevData, bool keepHandIndexPersistent, bool keepPointableIndexPersistent, const F32& maxHandAxisRadius);
|
||||
|
||||
/// Compare this data and given and return differences
|
||||
U32 compare(LeapMotionDeviceData* other);
|
||||
|
||||
/// Compare meta data between this and given and return differences
|
||||
U32 compareMeta(LeapMotionDeviceData* other);
|
||||
};
|
||||
|
||||
#endif // _LEAPMOTIONDATA_H_
|
||||
364
Engine/source/platform/input/leapMotion/leapMotionDevice.cpp
Normal file
364
Engine/source/platform/input/leapMotion/leapMotionDevice.cpp
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/input/leapMotion/leapMotionDevice.h"
|
||||
#include "platform/input/leapMotion/leapMotionData.h"
|
||||
#include "platform/input/leapMotion/leapMotionFrameStore.h"
|
||||
#include "platform/platformInput.h"
|
||||
#include "core/module.h"
|
||||
#include "platform/threads/mutex.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
MODULE_BEGIN( LeapMotionDevice )
|
||||
|
||||
MODULE_INIT_AFTER( InputEventManager )
|
||||
MODULE_SHUTDOWN_BEFORE( InputEventManager )
|
||||
|
||||
MODULE_INIT
|
||||
{
|
||||
LeapMotionDevice::staticInit();
|
||||
ManagedSingleton< LeapMotionDevice >::createSingleton();
|
||||
if(LeapMotionDevice::smEnableDevice)
|
||||
{
|
||||
LEAPMOTIONDEV->enable();
|
||||
}
|
||||
|
||||
// Register the device with the Input Event Manager
|
||||
INPUTMGR->registerDevice(LEAPMOTIONDEV);
|
||||
}
|
||||
|
||||
MODULE_SHUTDOWN
|
||||
{
|
||||
INPUTMGR->unregisterDevice(LEAPMOTIONDEV);
|
||||
ManagedSingleton< LeapMotionDevice >::deleteSingleton();
|
||||
}
|
||||
|
||||
MODULE_END;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LeapMotionDevice
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool LeapMotionDevice::smEnableDevice = true;
|
||||
|
||||
bool LeapMotionDevice::smGenerateIndividualEvents = true;
|
||||
bool LeapMotionDevice::smKeepHandIndexPersistent = false;
|
||||
bool LeapMotionDevice::smKeepPointableIndexPersistent = false;
|
||||
|
||||
bool LeapMotionDevice::smGenerateSingleHandRotationAsAxisEvents = false;
|
||||
|
||||
F32 LeapMotionDevice::smMaximumHandAxisAngle = 25.0f;
|
||||
|
||||
bool LeapMotionDevice::smGenerateWholeFrameEvents = false;
|
||||
|
||||
U32 LeapMotionDevice::LM_FRAMEVALIDDATA = 0;
|
||||
U32 LeapMotionDevice::LM_HAND[LeapMotionConstants::MaxHands] = {0};
|
||||
U32 LeapMotionDevice::LM_HANDROT[LeapMotionConstants::MaxHands] = {0};
|
||||
U32 LeapMotionDevice::LM_HANDAXISX = 0;
|
||||
U32 LeapMotionDevice::LM_HANDAXISY = 0;
|
||||
U32 LeapMotionDevice::LM_HANDPOINTABLE[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand] = {0};
|
||||
U32 LeapMotionDevice::LM_HANDPOINTABLEROT[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand] = {0};
|
||||
U32 LeapMotionDevice::LM_FRAME = 0;
|
||||
|
||||
LeapMotionDevice::LeapMotionDevice()
|
||||
{
|
||||
// From IInputDevice
|
||||
dStrcpy(mName, "leapmotion");
|
||||
mDeviceType = INPUTMGR->getNextDeviceType();
|
||||
|
||||
mController = NULL;
|
||||
mListener = NULL;
|
||||
mActiveMutex = Mutex::createMutex();
|
||||
|
||||
//
|
||||
mEnabled = false;
|
||||
mActive = false;
|
||||
|
||||
for(U32 i=0; i<2; ++i)
|
||||
{
|
||||
mDataBuffer[i] = new LeapMotionDeviceData();
|
||||
}
|
||||
mPrevData = mDataBuffer[0];
|
||||
|
||||
buildCodeTable();
|
||||
}
|
||||
|
||||
LeapMotionDevice::~LeapMotionDevice()
|
||||
{
|
||||
disable();
|
||||
|
||||
Mutex::destroyMutex(mActiveMutex);
|
||||
}
|
||||
|
||||
void LeapMotionDevice::staticInit()
|
||||
{
|
||||
Con::addVariable("pref::LeapMotion::EnableDevice", TypeBool, &smEnableDevice,
|
||||
"@brief If true, the Leap Motion device will be enabled, if present.\n\n"
|
||||
"@ingroup Game");
|
||||
|
||||
Con::addVariable("LeapMotion::GenerateIndividualEvents", TypeBool, &smGenerateIndividualEvents,
|
||||
"@brief Indicates that events for each hand and pointable will be created.\n\n"
|
||||
"@ingroup Game");
|
||||
Con::addVariable("LeapMotion::KeepHandIndexPersistent", TypeBool, &smKeepHandIndexPersistent,
|
||||
"@brief Indicates that we track hand IDs and will ensure that the same hand will remain at the same index between frames.\n\n"
|
||||
"@ingroup Game");
|
||||
Con::addVariable("LeapMotion::KeepPointableIndexPersistent", TypeBool, &smKeepPointableIndexPersistent,
|
||||
"@brief Indicates that we track pointable IDs and will ensure that the same pointable will remain at the same index between frames.\n\n"
|
||||
"@ingroup Game");
|
||||
|
||||
Con::addVariable("LeapMotion::GenerateSingleHandRotationAsAxisEvents", TypeBool, &smGenerateSingleHandRotationAsAxisEvents,
|
||||
"@brief If true, broadcast single hand rotation as axis events.\n\n"
|
||||
"@ingroup Game");
|
||||
Con::addVariable("LeapMotion::MaximumHandAxisAngle", TypeF32, &smMaximumHandAxisAngle,
|
||||
"@brief The maximum hand angle when used as an axis event as measured from a vector pointing straight up (in degrees).\n\n"
|
||||
"Shoud range from 0 to 90 degrees.\n\n"
|
||||
"@ingroup Game");
|
||||
|
||||
Con::addVariable("LeapMotion::GenerateWholeFrameEvents", TypeBool, &smGenerateWholeFrameEvents,
|
||||
"@brief Indicates that a whole frame event should be generated and frames should be buffered.\n\n"
|
||||
"@ingroup Game");
|
||||
}
|
||||
|
||||
void LeapMotionDevice::buildCodeTable()
|
||||
{
|
||||
// Obtain all of the device codes
|
||||
LM_FRAMEVALIDDATA = INPUTMGR->getNextDeviceCode();
|
||||
|
||||
for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
|
||||
{
|
||||
// Hands
|
||||
LM_HAND[i] = INPUTMGR->getNextDeviceCode();
|
||||
LM_HANDROT[i] = INPUTMGR->getNextDeviceCode();
|
||||
|
||||
// Pointables per hand
|
||||
for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
|
||||
{
|
||||
LM_HANDPOINTABLE[i][j] = INPUTMGR->getNextDeviceCode();
|
||||
LM_HANDPOINTABLEROT[i][j] = INPUTMGR->getNextDeviceCode();
|
||||
}
|
||||
}
|
||||
|
||||
LM_HANDAXISX = INPUTMGR->getNextDeviceCode();
|
||||
LM_HANDAXISY = INPUTMGR->getNextDeviceCode();
|
||||
|
||||
LM_FRAME = INPUTMGR->getNextDeviceCode();
|
||||
|
||||
// Build out the virtual map
|
||||
AddInputVirtualMap( lm_framevaliddata, SI_BUTTON, LM_FRAMEVALIDDATA );
|
||||
|
||||
char buffer[64];
|
||||
for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
|
||||
{
|
||||
// Hands
|
||||
dSprintf(buffer, 64, "lm_hand%d", i+1);
|
||||
INPUTMGR->addVirtualMap( buffer, SI_POS, LM_HAND[i] );
|
||||
dSprintf(buffer, 64, "lm_hand%drot", i+1);
|
||||
INPUTMGR->addVirtualMap( buffer, SI_ROT, LM_HANDROT[i] );
|
||||
|
||||
// Pointables per hand
|
||||
for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
|
||||
{
|
||||
dSprintf(buffer, 64, "lm_hand%dpoint%d", i+1, j+1);
|
||||
INPUTMGR->addVirtualMap( buffer, SI_POS, LM_HANDPOINTABLE[i][j] );
|
||||
dSprintf(buffer, 64, "lm_hand%dpoint%drot", i+1, j+1);
|
||||
INPUTMGR->addVirtualMap( buffer, SI_POS, LM_HANDPOINTABLEROT[i][j] );
|
||||
}
|
||||
}
|
||||
|
||||
AddInputVirtualMap( lm_handaxisx, SI_AXIS, LM_HANDAXISX );
|
||||
AddInputVirtualMap( lm_handaxisy, SI_AXIS, LM_HANDAXISY );
|
||||
|
||||
AddInputVirtualMap( lm_frame, SI_INT, LM_FRAME );
|
||||
}
|
||||
|
||||
bool LeapMotionDevice::enable()
|
||||
{
|
||||
// Start off with disabling the device if it is already enabled
|
||||
disable();
|
||||
|
||||
// Create the controller to talk with the Leap Motion along with the listener
|
||||
mListener = new MotionListener();
|
||||
mController = new Leap::Controller(*mListener);
|
||||
|
||||
// The device is now enabled but not yet ready to be used
|
||||
mEnabled = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LeapMotionDevice::disable()
|
||||
{
|
||||
if(mController)
|
||||
{
|
||||
delete mController;
|
||||
mController = NULL;
|
||||
|
||||
if(mListener)
|
||||
{
|
||||
delete mListener;
|
||||
mListener = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
setActive(false);
|
||||
mEnabled = false;
|
||||
}
|
||||
|
||||
bool LeapMotionDevice::getActive()
|
||||
{
|
||||
Mutex::lockMutex(mActiveMutex);
|
||||
bool active = mActive;
|
||||
Mutex::unlockMutex(mActiveMutex);
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
void LeapMotionDevice::setActive(bool state)
|
||||
{
|
||||
Mutex::lockMutex(mActiveMutex);
|
||||
mActive = state;
|
||||
Mutex::unlockMutex(mActiveMutex);
|
||||
}
|
||||
|
||||
bool LeapMotionDevice::process()
|
||||
{
|
||||
if(!mEnabled)
|
||||
return false;
|
||||
|
||||
if(!getActive())
|
||||
return false;
|
||||
|
||||
//Con::printf("LeapMotionDevice::process()");
|
||||
|
||||
//Build the maximum hand axis angle to be passed into the LeapMotionDeviceData::setData()
|
||||
F32 maxHandAxisRadius = mSin(mDegToRad(smMaximumHandAxisAngle));
|
||||
|
||||
// Get a frame of data
|
||||
const Leap::Frame frame = mController->frame();
|
||||
|
||||
//const Leap::HandList hands = frame.hands();
|
||||
//Con::printf("Frame: %lld Hands: %d Fingers: %d Tools: %d", (long long)frame.id(), hands.count(), frame.fingers().count(), frame.tools().count());
|
||||
|
||||
// Store the current data
|
||||
LeapMotionDeviceData* currentBuffer = (mPrevData == mDataBuffer[0]) ? mDataBuffer[1] : mDataBuffer[0];
|
||||
currentBuffer->setData(frame, mPrevData, smKeepHandIndexPersistent, smKeepPointableIndexPersistent, maxHandAxisRadius);
|
||||
U32 diff = mPrevData->compare(currentBuffer);
|
||||
U32 metaDiff = mPrevData->compareMeta(currentBuffer);
|
||||
|
||||
// Update the previous data pointers. We do this here in case someone calls our
|
||||
// console functions during one of the input events below.
|
||||
mPrevData = currentBuffer;
|
||||
|
||||
// Send out any meta data
|
||||
if(metaDiff & LeapMotionDeviceData::METADIFF_FRAME_VALID_DATA)
|
||||
{
|
||||
// Frame valid change event
|
||||
INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_BUTTON, LM_FRAMEVALIDDATA, currentBuffer->mHasTrackingData ? SI_MAKE : SI_BREAK, currentBuffer->mHasTrackingData ? 1.0f : 0.0f);
|
||||
}
|
||||
|
||||
// Send out any valid data
|
||||
if(currentBuffer->mDataSet && currentBuffer->mIsValid)
|
||||
{
|
||||
// Hands and their pointables
|
||||
if(smGenerateIndividualEvents)
|
||||
{
|
||||
for(U32 i=0; i<LeapMotionConstants::MaxHands; ++i)
|
||||
{
|
||||
if(currentBuffer->mHandValid[i])
|
||||
{
|
||||
// Send out position
|
||||
INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_POS, LM_HAND[i], SI_MOVE, currentBuffer->mHandPosPoint[i]);
|
||||
|
||||
// Send out rotation
|
||||
INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_ROT, LM_HANDROT[i], SI_MOVE, currentBuffer->mHandRotQuat[i]);
|
||||
|
||||
// Pointables for hand
|
||||
for(U32 j=0; j<LeapMotionConstants::MaxPointablesPerHand; ++j)
|
||||
{
|
||||
if(currentBuffer->mPointableValid[i][j])
|
||||
{
|
||||
// Send out position
|
||||
INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_POS, LM_HANDPOINTABLE[i][j], SI_MOVE, currentBuffer->mPointablePosPoint[i][j]);
|
||||
|
||||
// Send out rotation
|
||||
INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_ROT, LM_HANDPOINTABLEROT[i][j], SI_MOVE, currentBuffer->mPointableRotQuat[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Single Hand as axis rotation
|
||||
if(smGenerateSingleHandRotationAsAxisEvents && diff & LeapMotionDeviceData::DIFF_HANDROTAXIS)
|
||||
{
|
||||
if(diff & LeapMotionDeviceData::DIFF_HANDROTAXISX)
|
||||
INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_AXIS, LM_HANDAXISX, SI_MOVE, currentBuffer->mHandRotAxis[0]);
|
||||
if(diff & LeapMotionDeviceData::DIFF_HANDROTAXISY)
|
||||
INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_AXIS, LM_HANDAXISY, SI_MOVE, currentBuffer->mHandRotAxis[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Send out whole frame event, but only if the special frame group is defined
|
||||
if(smGenerateWholeFrameEvents && LeapMotionFrameStore::isFrameGroupDefined())
|
||||
{
|
||||
S32 id = LEAPMOTIONFS->generateNewFrame(frame, maxHandAxisRadius);
|
||||
if(id != 0)
|
||||
{
|
||||
INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_INT, LM_FRAME, SI_VALUE, id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LeapMotionDevice::MotionListener
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void LeapMotionDevice::MotionListener::onConnect (const Leap::Controller &controller)
|
||||
{
|
||||
LEAPMOTIONDEV->setActive(true);
|
||||
}
|
||||
|
||||
void LeapMotionDevice::MotionListener::onDisconnect (const Leap::Controller &controller)
|
||||
{
|
||||
LEAPMOTIONDEV->setActive(false);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineFunction(isLeapMotionActive, bool, (),,
|
||||
"@brief Used to determine if the Leap Motion input device is active\n\n"
|
||||
|
||||
"The Leap Motion input device is considered active when the support library has been "
|
||||
"loaded and the device has been found.\n\n"
|
||||
|
||||
"@return True if the Leap Motion input device is active.\n"
|
||||
|
||||
"@ingroup Game")
|
||||
{
|
||||
if(!ManagedSingleton<LeapMotionDevice>::instanceOrNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return LEAPMOTIONDEV->getActive();
|
||||
}
|
||||
138
Engine/source/platform/input/leapMotion/leapMotionDevice.h
Normal file
138
Engine/source/platform/input/leapMotion/leapMotionDevice.h
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LEAPMOTIONDEVICE_H_
|
||||
#define _LEAPMOTIONDEVICE_H_
|
||||
|
||||
#include "platform/input/IInputDevice.h"
|
||||
#include "platform/input/event.h"
|
||||
#include "platformWin32/platformWin32.h"
|
||||
#include "core/util/tSingleton.h"
|
||||
#include "math/mQuat.h"
|
||||
#include "platform/input/leapMotion/leapMotionConstants.h"
|
||||
#include "Leap.h"
|
||||
|
||||
#define DEFAULT_MOTION_UNIT 0
|
||||
|
||||
struct LeapMotionDeviceData;
|
||||
|
||||
class LeapMotionDevice : public IInputDevice
|
||||
{
|
||||
protected:
|
||||
class MotionListener : public Leap::Listener
|
||||
{
|
||||
public:
|
||||
MotionListener() {}
|
||||
virtual ~MotionListener() {}
|
||||
|
||||
virtual void onConnect (const Leap::Controller &controller);
|
||||
virtual void onDisconnect (const Leap::Controller &controller);
|
||||
};
|
||||
|
||||
/// The connection to the Leap Motion
|
||||
Leap::Controller* mController;
|
||||
|
||||
/// Our Leap Motion listener class
|
||||
MotionListener* mListener;
|
||||
|
||||
/// Used with the LM listener object
|
||||
void* mActiveMutex;
|
||||
|
||||
/// Is the Leap Motion active
|
||||
bool mActive;
|
||||
|
||||
/// Buffer to store data Leap Motion data in a Torque friendly way
|
||||
LeapMotionDeviceData* mDataBuffer[2];
|
||||
|
||||
/// Points to the buffers that holds the previously collected data
|
||||
LeapMotionDeviceData* mPrevData;
|
||||
|
||||
protected:
|
||||
/// Build out the codes used for controller actions with the
|
||||
/// Input Event Manager
|
||||
void buildCodeTable();
|
||||
|
||||
public:
|
||||
static bool smEnableDevice;
|
||||
|
||||
// Indicates that events for each hand and pointable will be created
|
||||
static bool smGenerateIndividualEvents;
|
||||
|
||||
// Indicates that we track hand IDs and will ensure that the same hand
|
||||
// will remain at the same index between frames.
|
||||
static bool smKeepHandIndexPersistent;
|
||||
|
||||
// Indicates that we track pointable IDs and will ensure that the same
|
||||
// pointable will remain at the same index between frames.
|
||||
static bool smKeepPointableIndexPersistent;
|
||||
|
||||
// Broadcast single hand rotation as axis
|
||||
static bool smGenerateSingleHandRotationAsAxisEvents;
|
||||
|
||||
// The maximum hand angle when used as an axis event
|
||||
// as measured from a vector pointing straight up (in degrees)
|
||||
static F32 smMaximumHandAxisAngle;
|
||||
|
||||
// Indicates that a whole frame event should be generated and frames
|
||||
// should be buffered.
|
||||
static bool smGenerateWholeFrameEvents;
|
||||
|
||||
// Frame action codes
|
||||
static U32 LM_FRAMEVALIDDATA; // SI_BUTTON
|
||||
|
||||
// Hand action codes
|
||||
static U32 LM_HAND[LeapMotionConstants::MaxHands]; // SI_POS
|
||||
static U32 LM_HANDROT[LeapMotionConstants::MaxHands]; // SI_ROT
|
||||
|
||||
static U32 LM_HANDAXISX; // SI_AXIS
|
||||
static U32 LM_HANDAXISY;
|
||||
|
||||
// Pointables action codes
|
||||
static U32 LM_HANDPOINTABLE[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; // SI_POS
|
||||
static U32 LM_HANDPOINTABLEROT[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; // SI_ROT
|
||||
|
||||
// Whole frame
|
||||
static U32 LM_FRAME; // SI_INT
|
||||
|
||||
public:
|
||||
LeapMotionDevice();
|
||||
~LeapMotionDevice();
|
||||
|
||||
static void staticInit();
|
||||
|
||||
bool enable();
|
||||
void disable();
|
||||
|
||||
bool getActive();
|
||||
void setActive(bool state);
|
||||
|
||||
bool process();
|
||||
|
||||
public:
|
||||
// For ManagedSingleton.
|
||||
static const char* getSingletonName() { return "LeapMotionDevice"; }
|
||||
};
|
||||
|
||||
/// Returns the LeapMotionDevice singleton.
|
||||
#define LEAPMOTIONDEV ManagedSingleton<LeapMotionDevice>::instance()
|
||||
|
||||
#endif // _LEAPMOTIONDEVICE_H_
|
||||
497
Engine/source/platform/input/leapMotion/leapMotionFrame.cpp
Normal file
497
Engine/source/platform/input/leapMotion/leapMotionFrame.cpp
Normal file
|
|
@ -0,0 +1,497 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/input/leapMotion/leapMotionFrame.h"
|
||||
#include "platform/input/leapMotion/leapMotionUtil.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "math/mAngAxis.h"
|
||||
#include "math/mTransform.h"
|
||||
|
||||
U32 LeapMotionFrame::smNextInternalFrameId = 0;
|
||||
|
||||
IMPLEMENT_CONOBJECT(LeapMotionFrame);
|
||||
|
||||
ImplementEnumType( LeapMotionFramePointableType,
|
||||
"Leap Motion pointable type.\n\n")
|
||||
{ LeapMotionFrame::PT_UNKNOWN, "Unknown", "Unknown pointable type.\n" },
|
||||
{ LeapMotionFrame::PT_FINGER, "Finger", "Finger pointable type.\n" },
|
||||
{ LeapMotionFrame::PT_TOOL, "Tool", "Tool pointable type.\n" },
|
||||
EndImplementEnumType;
|
||||
|
||||
LeapMotionFrame::LeapMotionFrame()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
LeapMotionFrame::~LeapMotionFrame()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void LeapMotionFrame::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
bool LeapMotionFrame::onAdd()
|
||||
{
|
||||
if (!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LeapMotionFrame::onRemove()
|
||||
{
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
void LeapMotionFrame::clear()
|
||||
{
|
||||
mFrameValid = false;
|
||||
|
||||
mHandCount = 0;
|
||||
mHandValid.clear();
|
||||
mHandId.clear();
|
||||
mHandRawPos.clear();
|
||||
mHandPos.clear();
|
||||
mHandRot.clear();
|
||||
mHandRotQuat.clear();
|
||||
mHandRotAxis.clear();
|
||||
mHandPointablesCount.clear();
|
||||
|
||||
mPointableCount = 0;
|
||||
mPointableValid.clear();
|
||||
mPointableId.clear();
|
||||
mPointableHandIndex.clear();
|
||||
mPointableType.clear();
|
||||
mPointableRawPos.clear();
|
||||
mPointablePos.clear();
|
||||
mPointableRot.clear();
|
||||
mPointableRotQuat.clear();
|
||||
mPointableLength.clear();
|
||||
mPointableWidth.clear();
|
||||
}
|
||||
|
||||
void LeapMotionFrame::copyFromFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius)
|
||||
{
|
||||
// This also resets all counters
|
||||
clear();
|
||||
|
||||
// Retrieve frame information
|
||||
mFrameValid = frame.isValid();
|
||||
mFrameId = frame.id();
|
||||
mFrameTimeStamp = frame.timestamp();
|
||||
|
||||
mFrameInternalId = smNextInternalFrameId;
|
||||
++smNextInternalFrameId;
|
||||
mFrameSimTime = Sim::getCurrentTime();
|
||||
mFrameRealTime = Platform::getRealMilliseconds();
|
||||
|
||||
if(!mFrameValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve hand information
|
||||
mHandCount = frame.hands().count();
|
||||
if(mHandCount > 0)
|
||||
{
|
||||
copyFromFrameHands(frame.hands(), maxHandAxisRadius);
|
||||
}
|
||||
|
||||
// Retrieve pointable information
|
||||
mPointableCount = frame.pointables().count();
|
||||
if(mPointableCount > 0)
|
||||
{
|
||||
copyFromFramePointables(frame.pointables());
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionFrame::copyFromFrameHands(const Leap::HandList& hands, const F32& maxHandAxisRadius)
|
||||
{
|
||||
// Set up Vectors
|
||||
mHandValid.increment(mHandCount);
|
||||
mHandId.increment(mHandCount);
|
||||
mHandRawPos.increment(mHandCount);
|
||||
mHandPos.increment(mHandCount);
|
||||
mHandRot.increment(mHandCount);
|
||||
mHandRotQuat.increment(mHandCount);
|
||||
mHandRotAxis.increment(mHandCount);
|
||||
mHandPointablesCount.increment(mHandCount);
|
||||
|
||||
// Copy data
|
||||
for(U32 i=0; i<mHandCount; ++i)
|
||||
{
|
||||
const Leap::Hand& hand = hands[i];
|
||||
|
||||
mHandValid[i] = hand.isValid();
|
||||
mHandId[i] = hand.id();
|
||||
|
||||
// Position
|
||||
LeapMotionUtil::convertPosition(hand.palmPosition(), mHandRawPos[i]);
|
||||
mHandPos[i].x = (S32)mFloor(mHandRawPos[i].x);
|
||||
mHandPos[i].y = (S32)mFloor(mHandRawPos[i].y);
|
||||
mHandPos[i].z = (S32)mFloor(mHandRawPos[i].z);
|
||||
|
||||
// Rotation
|
||||
LeapMotionUtil::convertHandRotation(hand, mHandRot[i]);
|
||||
mHandRotQuat[i].set(mHandRot[i]);
|
||||
|
||||
// Thumb stick axis rotation
|
||||
LeapMotionUtil::calculateHandAxisRotation(mHandRot[i], maxHandAxisRadius, mHandRotAxis[i]);
|
||||
|
||||
// Pointables
|
||||
mHandPointablesCount[i] = hand.pointables().count();
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionFrame::copyFromFramePointables(const Leap::PointableList& pointables)
|
||||
{
|
||||
// Set up Vectors
|
||||
mPointableValid.increment(mPointableCount);
|
||||
mPointableId.increment(mPointableCount);
|
||||
mPointableHandIndex.increment(mPointableCount);
|
||||
mPointableType.increment(mPointableCount);
|
||||
mPointableRawPos.increment(mPointableCount);
|
||||
mPointablePos.increment(mPointableCount);
|
||||
mPointableRot.increment(mPointableCount);
|
||||
mPointableRotQuat.increment(mPointableCount);
|
||||
mPointableLength.increment(mPointableCount);
|
||||
mPointableWidth.increment(mPointableCount);
|
||||
|
||||
// Copy data
|
||||
for(U32 i=0; i<mPointableCount; ++i)
|
||||
{
|
||||
const Leap::Pointable& pointable = pointables[i];
|
||||
|
||||
mPointableValid[i] = pointable.isValid();
|
||||
mPointableId[i] = pointable.id();
|
||||
mPointableLength[i] = pointable.length();
|
||||
mPointableWidth[i] = pointable.width();
|
||||
|
||||
mPointableType[i] = PT_UNKNOWN;
|
||||
if(pointable.isFinger())
|
||||
{
|
||||
mPointableType[i] = PT_FINGER;
|
||||
}
|
||||
else if(pointable.isTool())
|
||||
{
|
||||
mPointableType[i] = PT_TOOL;
|
||||
}
|
||||
|
||||
// Which hand, if any
|
||||
const Leap::Hand& hand = pointable.hand();
|
||||
if(hand.isValid())
|
||||
{
|
||||
bool found = false;
|
||||
S32 handId = hand.id();
|
||||
for(U32 j=0; j<mHandCount; ++j)
|
||||
{
|
||||
if(mHandId[j] == handId)
|
||||
{
|
||||
mPointableHandIndex[i] = j;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
mPointableHandIndex[i] = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mPointableHandIndex[i] = -1;
|
||||
}
|
||||
|
||||
// Position
|
||||
LeapMotionUtil::convertPosition(pointable.tipPosition(), mPointableRawPos[i]);
|
||||
mPointablePos[i].x = (S32)mFloor(mPointableRawPos[i].x);
|
||||
mPointablePos[i].y = (S32)mFloor(mPointableRawPos[i].y);
|
||||
mPointablePos[i].z = (S32)mFloor(mPointableRawPos[i].z);
|
||||
|
||||
// Rotation
|
||||
LeapMotionUtil::convertPointableRotation(pointable, mPointableRot[i]);
|
||||
mPointableRotQuat[i].set(mPointableRot[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, isFrameValid, bool, ( ),,
|
||||
"@brief Checks if this frame is valid.\n\n"
|
||||
"@return True if the frame is valid.\n\n")
|
||||
{
|
||||
return object->isFrameValid();
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getFrameInternalId, S32, ( ),,
|
||||
"@brief Provides the internal ID for this frame.\n\n"
|
||||
"@return Internal ID of this frame.\n\n")
|
||||
{
|
||||
return object->getFrameInternalId();
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getFrameSimTime, S32, ( ),,
|
||||
"@brief Get the sim time that this frame was generated.\n\n"
|
||||
"@return Sim time of this frame in milliseconds.\n\n")
|
||||
{
|
||||
return object->getFrameSimTime();
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getFrameRealTime, S32, ( ),,
|
||||
"@brief Get the real time that this frame was generated.\n\n"
|
||||
"@return Real time of this frame in milliseconds.\n\n")
|
||||
{
|
||||
return object->getFrameRealTime();
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandCount, S32, ( ),,
|
||||
"@brief Get the number of hands defined in this frame.\n\n"
|
||||
"@return The number of defined hands.\n\n")
|
||||
{
|
||||
return object->getHandCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandValid, bool, ( S32 index ),,
|
||||
"@brief Check if the requested hand is valid.\n\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return True if the hand is valid.\n\n")
|
||||
{
|
||||
return object->getHandValid(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandId, S32, ( S32 index ),,
|
||||
"@brief Get the ID of the requested hand.\n\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return ID of the requested hand.\n\n")
|
||||
{
|
||||
return object->getHandId(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandRawPos, Point3F, ( S32 index ),,
|
||||
"@brief Get the raw position of the requested hand.\n\n"
|
||||
"The raw position is the hand's floating point position converted to "
|
||||
"Torque 3D coordinates (in millimeters).\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return Raw position of the requested hand.\n\n")
|
||||
{
|
||||
return object->getHandRawPos(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandPos, Point3I, ( S32 index ),,
|
||||
"@brief Get the position of the requested hand.\n\n"
|
||||
"The position is the hand's integer position converted to "
|
||||
"Torque 3D coordinates (in millimeters).\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return Integer position of the requested hand (in millimeters).\n\n")
|
||||
{
|
||||
return object->getHandPos(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandRot, AngAxisF, ( S32 index ),,
|
||||
"@brief Get the rotation of the requested hand.\n\n"
|
||||
"The Leap Motion hand rotation as converted into the Torque 3D"
|
||||
"coordinate system.\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return Rotation of the requested hand.\n\n")
|
||||
{
|
||||
AngAxisF aa(object->getHandRot(index));
|
||||
return aa;
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandRawTransform, TransformF, ( S32 index ),,
|
||||
"@brief Get the raw transform of the requested hand.\n\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return The raw position and rotation of the requested hand (in Torque 3D coordinates).\n\n")
|
||||
{
|
||||
const Point3F& pos = object->getHandRawPos(index);
|
||||
const QuatF& qa = object->getHandRotQuat(index);
|
||||
|
||||
AngAxisF aa(qa);
|
||||
aa.axis.normalize();
|
||||
|
||||
TransformF trans(pos, aa);
|
||||
return trans;
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandTransform, TransformF, ( S32 index ),,
|
||||
"@brief Get the transform of the requested hand.\n\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return The position and rotation of the requested hand (in Torque 3D coordinates).\n\n")
|
||||
{
|
||||
const Point3I& pos = object->getHandPos(index);
|
||||
const QuatF& qa = object->getHandRotQuat(index);
|
||||
|
||||
AngAxisF aa(qa);
|
||||
aa.axis.normalize();
|
||||
|
||||
TransformF trans;
|
||||
trans.mPosition = Point3F(pos.x, pos.y, pos.z);
|
||||
trans.mOrientation = aa;
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandRotAxis, Point2F, ( S32 index ),,
|
||||
"@brief Get the axis rotation of the requested hand.\n\n"
|
||||
"This is the axis rotation of the hand as if the hand were a gamepad thumb stick. "
|
||||
"Imagine a stick coming out the top of the hand and tilting the hand front, back, "
|
||||
"left and right controls that stick. The values returned along the x and y stick "
|
||||
"axis are normalized from -1.0 to 1.0 with the maximum hand tilt angle for these "
|
||||
"values as defined by $LeapMotion::MaximumHandAxisAngle.\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return Axis rotation of the requested hand.\n\n"
|
||||
"@see LeapMotion::MaximumHandAxisAngle\n")
|
||||
{
|
||||
return object->getHandRotAxis(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getHandPointablesCount, S32, ( S32 index ),,
|
||||
"@brief Get the number of pointables associated with this hand.\n\n"
|
||||
"@param index The hand index to check.\n"
|
||||
"@return Number of pointables that belong with this hand.\n\n")
|
||||
{
|
||||
return object->getHandPointablesCount(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointablesCount, S32, ( ),,
|
||||
"@brief Get the number of pointables defined in this frame.\n\n"
|
||||
"@return The number of defined pointables.\n\n")
|
||||
{
|
||||
return object->getPointablesCount();
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableValid, bool, ( S32 index ),,
|
||||
"@brief Check if the requested pointable is valid.\n\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return True if the pointable is valid.\n\n")
|
||||
{
|
||||
return object->getPointableValid(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableId, S32, ( S32 index ),,
|
||||
"@brief Get the ID of the requested pointable.\n\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return ID of the requested pointable.\n\n")
|
||||
{
|
||||
return object->getPointableId(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableHandIndex, S32, ( S32 index ),,
|
||||
"@brief Get the index of the hand that this pointable belongs to, if any.\n\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return Index of the hand this pointable belongs to, or -1 if there is no associated hand.\n\n")
|
||||
{
|
||||
return object->getPointableHandIndex(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableType, LeapMotionFramePointableType, ( S32 index ),,
|
||||
"@brief Get the type of the requested pointable.\n\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return Type of the requested pointable.\n\n")
|
||||
{
|
||||
return object->getPointableType(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableRawPos, Point3F, ( S32 index ),,
|
||||
"@brief Get the raw position of the requested pointable.\n\n"
|
||||
"The raw position is the pointable's floating point position converted to "
|
||||
"Torque 3D coordinates (in millimeters).\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return Raw position of the requested pointable.\n\n")
|
||||
{
|
||||
return object->getPointableRawPos(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointablePos, Point3I, ( S32 index ),,
|
||||
"@brief Get the position of the requested pointable.\n\n"
|
||||
"The position is the pointable's integer position converted to "
|
||||
"Torque 3D coordinates (in millimeters).\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return Integer position of the requested pointable (in millimeters).\n\n")
|
||||
{
|
||||
return object->getPointablePos(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableRot, AngAxisF, ( S32 index ),,
|
||||
"@brief Get the rotation of the requested pointable.\n\n"
|
||||
"The Leap Motion pointable rotation as converted into the Torque 3D"
|
||||
"coordinate system.\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return Rotation of the requested pointable.\n\n")
|
||||
{
|
||||
AngAxisF aa(object->getPointableRot(index));
|
||||
return aa;
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableRawTransform, TransformF, ( S32 index ),,
|
||||
"@brief Get the raw transform of the requested pointable.\n\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return The raw position and rotation of the requested pointable (in Torque 3D coordinates).\n\n")
|
||||
{
|
||||
const Point3F& pos = object->getPointableRawPos(index);
|
||||
const QuatF& qa = object->getPointableRotQuat(index);
|
||||
|
||||
AngAxisF aa(qa);
|
||||
aa.axis.normalize();
|
||||
|
||||
TransformF trans(pos, aa);
|
||||
return trans;
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableTransform, TransformF, ( S32 index ),,
|
||||
"@brief Get the transform of the requested pointable.\n\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return The position and rotation of the requested pointable (in Torque 3D coordinates).\n\n")
|
||||
{
|
||||
const Point3I& pos = object->getPointablePos(index);
|
||||
const QuatF& qa = object->getPointableRotQuat(index);
|
||||
|
||||
AngAxisF aa(qa);
|
||||
aa.axis.normalize();
|
||||
|
||||
TransformF trans;
|
||||
trans.mPosition = Point3F(pos.x, pos.y, pos.z);
|
||||
trans.mOrientation = aa;
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableLength, F32, ( S32 index ),,
|
||||
"@brief Get the length of the requested pointable.\n\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return Length of the requested pointable (in millimeters).\n\n")
|
||||
{
|
||||
return object->getPointableLength(index);
|
||||
}
|
||||
|
||||
DefineEngineMethod( LeapMotionFrame, getPointableWidth, F32, ( S32 index ),,
|
||||
"@brief Get the width of the requested pointable.\n\n"
|
||||
"@param index The pointable index to check.\n"
|
||||
"@return Width of the requested pointable (in millimeters).\n\n")
|
||||
{
|
||||
return object->getPointableWidth(index);
|
||||
}
|
||||
227
Engine/source/platform/input/leapMotion/leapMotionFrame.h
Normal file
227
Engine/source/platform/input/leapMotion/leapMotionFrame.h
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LEAPMOTIONFRAME_H_
|
||||
#define _LEAPMOTIONFRAME_H_
|
||||
|
||||
#include "console/simObject.h"
|
||||
#include "math/mPoint3.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "math/mQuat.h"
|
||||
#include "Leap.h"
|
||||
|
||||
class LeapMotionFrame : public SimObject
|
||||
{
|
||||
typedef SimObject Parent;
|
||||
|
||||
public:
|
||||
enum PointableType
|
||||
{
|
||||
PT_UNKNOWN = -1,
|
||||
PT_FINGER = 0,
|
||||
PT_TOOL,
|
||||
};
|
||||
|
||||
protected:
|
||||
static U32 smNextInternalFrameId;
|
||||
|
||||
// Frame
|
||||
bool mFrameValid;
|
||||
U64 mFrameId;
|
||||
U64 mFrameTimeStamp;
|
||||
|
||||
// Torque 3D frame information
|
||||
U32 mFrameInternalId;
|
||||
S32 mFrameSimTime;
|
||||
S32 mFrameRealTime;
|
||||
|
||||
// Hands
|
||||
U32 mHandCount;
|
||||
Vector<bool> mHandValid;
|
||||
Vector<S32> mHandId;
|
||||
Vector<Point3F> mHandRawPos;
|
||||
Vector<Point3I> mHandPos;
|
||||
Vector<MatrixF> mHandRot;
|
||||
Vector<QuatF> mHandRotQuat;
|
||||
Vector<Point2F> mHandRotAxis;
|
||||
Vector<U32> mHandPointablesCount;
|
||||
|
||||
// Pointables
|
||||
U32 mPointableCount;
|
||||
Vector<bool> mPointableValid;
|
||||
Vector<S32> mPointableId;
|
||||
Vector<S32> mPointableHandIndex;
|
||||
Vector<PointableType> mPointableType;
|
||||
Vector<Point3F> mPointableRawPos;
|
||||
Vector<Point3I> mPointablePos;
|
||||
Vector<MatrixF> mPointableRot;
|
||||
Vector<QuatF> mPointableRotQuat;
|
||||
Vector<F32> mPointableLength;
|
||||
Vector<F32> mPointableWidth;
|
||||
|
||||
protected:
|
||||
void copyFromFrameHands(const Leap::HandList& hands, const F32& maxHandAxisRadius);
|
||||
void copyFromFramePointables(const Leap::PointableList& pointables);
|
||||
|
||||
public:
|
||||
LeapMotionFrame();
|
||||
virtual ~LeapMotionFrame();
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
|
||||
void clear();
|
||||
|
||||
/// Copy a Leap Frame into our data structures
|
||||
void copyFromFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius);
|
||||
|
||||
// Frame
|
||||
bool isFrameValid() const { return mFrameValid; }
|
||||
U32 getFrameInternalId() const { return mFrameInternalId; }
|
||||
S32 getFrameSimTime() const { return mFrameSimTime; }
|
||||
S32 getFrameRealTime() const { return mFrameRealTime; }
|
||||
|
||||
// Hands
|
||||
U32 getHandCount() const { return mHandCount; }
|
||||
bool getHandValid(U32 index) const;
|
||||
S32 getHandId(U32 index) const;
|
||||
const Point3F& getHandRawPos(U32 index) const;
|
||||
const Point3I& getHandPos(U32 index) const;
|
||||
const MatrixF& getHandRot(U32 index) const;
|
||||
const QuatF& getHandRotQuat(U32 index) const;
|
||||
const Point2F& getHandRotAxis(U32 index) const;
|
||||
U32 getHandPointablesCount(U32 index) const;
|
||||
|
||||
// Pointables
|
||||
U32 getPointablesCount() const { return mPointableCount; }
|
||||
bool getPointableValid(U32 index) const;
|
||||
S32 getPointableId(U32 index) const;
|
||||
S32 getPointableHandIndex(U32 index) const;
|
||||
PointableType getPointableType(U32 index) const;
|
||||
const Point3F& getPointableRawPos(U32 index) const;
|
||||
const Point3I& getPointablePos(U32 index) const;
|
||||
const MatrixF& getPointableRot(U32 index) const;
|
||||
const QuatF& getPointableRotQuat(U32 index) const;
|
||||
F32 getPointableLength(U32 index) const;
|
||||
F32 getPointableWidth(U32 index) const;
|
||||
|
||||
DECLARE_CONOBJECT(LeapMotionFrame);
|
||||
};
|
||||
|
||||
typedef LeapMotionFrame::PointableType LeapMotionFramePointableType;
|
||||
DefineEnumType( LeapMotionFramePointableType );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline bool LeapMotionFrame::getHandValid(U32 index) const
|
||||
{
|
||||
return (index < mHandCount && mHandValid[index]);
|
||||
}
|
||||
|
||||
inline S32 LeapMotionFrame::getHandId(U32 index) const
|
||||
{
|
||||
return (index >= mHandCount) ? -1 : mHandId[index];
|
||||
}
|
||||
|
||||
inline const Point3F& LeapMotionFrame::getHandRawPos(U32 index) const
|
||||
{
|
||||
return (index >= mHandCount) ? Point3F::Zero : mHandRawPos[index];
|
||||
}
|
||||
|
||||
inline const Point3I& LeapMotionFrame::getHandPos(U32 index) const
|
||||
{
|
||||
return (index >= mHandCount) ? Point3I::Zero : mHandPos[index];
|
||||
}
|
||||
|
||||
inline const MatrixF& LeapMotionFrame::getHandRot(U32 index) const
|
||||
{
|
||||
return (index >= mHandCount) ? MatrixF::Identity : mHandRot[index];
|
||||
}
|
||||
|
||||
inline const QuatF& LeapMotionFrame::getHandRotQuat(U32 index) const
|
||||
{
|
||||
return (index >= mHandCount) ? QuatF::Identity : mHandRotQuat[index];
|
||||
}
|
||||
|
||||
inline const Point2F& LeapMotionFrame::getHandRotAxis(U32 index) const
|
||||
{
|
||||
return (index >= mHandCount) ? Point2F::Zero : mHandRotAxis[index];
|
||||
}
|
||||
|
||||
inline U32 LeapMotionFrame::getHandPointablesCount(U32 index) const
|
||||
{
|
||||
return (index >= mHandCount) ? 0 : mHandPointablesCount[index];
|
||||
}
|
||||
|
||||
inline bool LeapMotionFrame::getPointableValid(U32 index) const
|
||||
{
|
||||
return (index < mPointableCount && mPointableValid[index]);
|
||||
}
|
||||
|
||||
inline S32 LeapMotionFrame::getPointableId(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? -1 : mPointableId[index];
|
||||
}
|
||||
|
||||
inline S32 LeapMotionFrame::getPointableHandIndex(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? -1 : mPointableHandIndex[index];
|
||||
}
|
||||
|
||||
inline LeapMotionFrame::PointableType LeapMotionFrame::getPointableType(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? PT_UNKNOWN : mPointableType[index];
|
||||
}
|
||||
|
||||
inline const Point3F& LeapMotionFrame::getPointableRawPos(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? Point3F::Zero : mPointableRawPos[index];
|
||||
}
|
||||
|
||||
inline const Point3I& LeapMotionFrame::getPointablePos(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? Point3I::Zero : mPointablePos[index];
|
||||
}
|
||||
|
||||
inline const MatrixF& LeapMotionFrame::getPointableRot(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? MatrixF::Identity : mPointableRot[index];
|
||||
}
|
||||
|
||||
inline const QuatF& LeapMotionFrame::getPointableRotQuat(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? QuatF::Identity : mPointableRotQuat[index];
|
||||
}
|
||||
|
||||
inline F32 LeapMotionFrame::getPointableLength(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? 0.0f : mPointableLength[index];
|
||||
}
|
||||
|
||||
inline F32 LeapMotionFrame::getPointableWidth(U32 index) const
|
||||
{
|
||||
return (index >= mPointableCount) ? 0.0f : mPointableWidth[index];
|
||||
}
|
||||
|
||||
#endif // _LEAPMOTIONFRAME_H_
|
||||
106
Engine/source/platform/input/leapMotion/leapMotionFrameStore.cpp
Normal file
106
Engine/source/platform/input/leapMotion/leapMotionFrameStore.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/input/leapMotion/leapMotionFrameStore.h"
|
||||
#include "platform/input/leapMotion/leapMotionFrame.h"
|
||||
#include "core/module.h"
|
||||
#include "console/simSet.h"
|
||||
#include "console/consoleTypes.h"
|
||||
|
||||
MODULE_BEGIN( LeapMotionFrameStore )
|
||||
|
||||
MODULE_INIT_AFTER( LeapMotionDevice )
|
||||
MODULE_INIT_AFTER( Sim )
|
||||
MODULE_SHUTDOWN_BEFORE( Sim )
|
||||
MODULE_SHUTDOWN_BEFORE( LeapMotionDevice )
|
||||
|
||||
MODULE_INIT
|
||||
{
|
||||
LeapMotionFrameStore::staticInit();
|
||||
ManagedSingleton< LeapMotionFrameStore >::createSingleton();
|
||||
}
|
||||
|
||||
MODULE_SHUTDOWN
|
||||
{
|
||||
ManagedSingleton< LeapMotionFrameStore >::deleteSingleton();
|
||||
}
|
||||
|
||||
MODULE_END;
|
||||
|
||||
S32 LeapMotionFrameStore::smMaximumFramesStored = 30;
|
||||
|
||||
SimGroup* LeapMotionFrameStore::smFrameGroup = NULL;
|
||||
|
||||
LeapMotionFrameStore::LeapMotionFrameStore()
|
||||
{
|
||||
// Set up the SimGroup to store our frames
|
||||
smFrameGroup = new SimGroup();
|
||||
smFrameGroup->registerObject("LeapMotionFrameGroup");
|
||||
smFrameGroup->setNameChangeAllowed(false);
|
||||
Sim::getRootGroup()->addObject(smFrameGroup);
|
||||
}
|
||||
|
||||
LeapMotionFrameStore::~LeapMotionFrameStore()
|
||||
{
|
||||
if(smFrameGroup)
|
||||
{
|
||||
smFrameGroup->deleteObject();
|
||||
smFrameGroup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void LeapMotionFrameStore::staticInit()
|
||||
{
|
||||
Con::addVariable("LeapMotion::MaximumFramesStored", TypeS32, &smMaximumFramesStored,
|
||||
"@brief The maximum number of frames to keep when $LeapMotion::GenerateWholeFrameEvents is true.\n\n"
|
||||
"@ingroup Game");
|
||||
}
|
||||
|
||||
S32 LeapMotionFrameStore::generateNewFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius)
|
||||
{
|
||||
// Make sure our group has been created
|
||||
if(!smFrameGroup)
|
||||
return 0;
|
||||
|
||||
// Either create a new frame object or pull one off the end
|
||||
S32 frameID = 0;
|
||||
if(smFrameGroup->size() >= smMaximumFramesStored)
|
||||
{
|
||||
// Make the last frame the first and update
|
||||
LeapMotionFrame* frameObj = static_cast<LeapMotionFrame*>(smFrameGroup->last());
|
||||
smFrameGroup->bringObjectToFront(frameObj);
|
||||
frameObj->copyFromFrame(frame, maxHandAxisRadius);
|
||||
frameID = frameObj->getId();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new frame and add it to the front of the list
|
||||
LeapMotionFrame* frameObj = new LeapMotionFrame();
|
||||
frameObj->registerObject();
|
||||
smFrameGroup->addObject(frameObj);
|
||||
smFrameGroup->bringObjectToFront(frameObj);
|
||||
frameObj->copyFromFrame(frame, maxHandAxisRadius);
|
||||
frameID = frameObj->getId();
|
||||
}
|
||||
|
||||
return frameID;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LEAPMOTIONFRAMESTORE_H_
|
||||
#define _LEAPMOTIONFRAMESTORE_H_
|
||||
|
||||
#include "platformWin32/platformWin32.h"
|
||||
#include "Leap.h"
|
||||
|
||||
class SimGroup;
|
||||
|
||||
class LeapMotionFrameStore
|
||||
{
|
||||
public:
|
||||
// The maximum number of frames to keep
|
||||
static S32 smMaximumFramesStored;
|
||||
|
||||
static SimGroup* smFrameGroup;
|
||||
|
||||
public:
|
||||
LeapMotionFrameStore();
|
||||
virtual ~LeapMotionFrameStore();
|
||||
|
||||
static void staticInit();
|
||||
|
||||
static bool isFrameGroupDefined() { return smFrameGroup != NULL; }
|
||||
static SimGroup* getFrameGroup() { return smFrameGroup; }
|
||||
|
||||
S32 generateNewFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius);
|
||||
|
||||
public:
|
||||
// For ManagedSingleton.
|
||||
static const char* getSingletonName() { return "LeapMotionFrameStore"; }
|
||||
};
|
||||
|
||||
/// Returns the LeapMotionFrameStore singleton.
|
||||
#define LEAPMOTIONFS ManagedSingleton<LeapMotionFrameStore>::instance()
|
||||
|
||||
#endif // _LEAPMOTIONFRAMESTORE_H_
|
||||
109
Engine/source/platform/input/leapMotion/leapMotionUtil.cpp
Normal file
109
Engine/source/platform/input/leapMotion/leapMotionUtil.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/input/leapMotion/leapMotionUtil.h"
|
||||
|
||||
namespace LeapMotionUtil
|
||||
{
|
||||
|
||||
void convertPosition(const Leap::Vector& inPosition, F32& x, F32& y, F32& z)
|
||||
{
|
||||
// Convert to Torque coordinates. The conversion is:
|
||||
//
|
||||
// Motion Torque
|
||||
// x y z --> x -z y
|
||||
x = inPosition.x; // x = x
|
||||
y = -inPosition.z; // y = -z
|
||||
z = inPosition.y; // z = y;
|
||||
}
|
||||
|
||||
void convertPosition(const Leap::Vector& inPosition, Point3F& outPosition)
|
||||
{
|
||||
// Convert to Torque coordinates. The conversion is:
|
||||
//
|
||||
// Motion Torque
|
||||
// x y z --> x -z y
|
||||
outPosition.x = inPosition.x; // x = x
|
||||
outPosition.y = -inPosition.z; // y = -z
|
||||
outPosition.z = inPosition.y; // z = y;
|
||||
}
|
||||
|
||||
void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation)
|
||||
{
|
||||
// We need to convert from Motion coordinates to
|
||||
// Torque coordinates. The conversion is:
|
||||
//
|
||||
// Motion Torque
|
||||
// a b c a b c a -c b
|
||||
// d e f --> -g -h -i --> -g i -h
|
||||
// g h i d e f d -f e
|
||||
const Leap::Vector& handToFingers = hand.direction();
|
||||
Leap::Vector handFront = -handToFingers;
|
||||
const Leap::Vector& handDown = hand.palmNormal();
|
||||
Leap::Vector handUp = -handDown;
|
||||
Leap::Vector handRight = handUp.cross(handFront);
|
||||
|
||||
outRotation.setColumn(0, Point4F( handRight.x, -handRight.z, handRight.y, 0.0f));
|
||||
outRotation.setColumn(1, Point4F( -handFront.x, handFront.z, -handFront.y, 0.0f));
|
||||
outRotation.setColumn(2, Point4F( handUp.x, -handUp.z, handUp.y, 0.0f));
|
||||
outRotation.setPosition(Point3F::Zero);
|
||||
}
|
||||
|
||||
void calculateHandAxisRotation(const MatrixF& handRotation, const F32& maxHandAxisRadius, Point2F& outRotation)
|
||||
{
|
||||
const VectorF& controllerUp = handRotation.getUpVector();
|
||||
outRotation.x = controllerUp.x;
|
||||
outRotation.y = controllerUp.y;
|
||||
|
||||
// Limit the axis angle to that given to us
|
||||
if(outRotation.len() > maxHandAxisRadius)
|
||||
{
|
||||
outRotation.normalize(maxHandAxisRadius);
|
||||
}
|
||||
|
||||
// Renormalize to the range of 0..1
|
||||
if(maxHandAxisRadius != 0.0f)
|
||||
{
|
||||
outRotation /= maxHandAxisRadius;
|
||||
}
|
||||
}
|
||||
|
||||
void convertPointableRotation(const Leap::Pointable& pointable, MatrixF& outRotation)
|
||||
{
|
||||
// We need to convert from Motion coordinates to
|
||||
// Torque coordinates. The conversion is:
|
||||
//
|
||||
// Motion Torque
|
||||
// a b c a b c a -c b
|
||||
// d e f --> -g -h -i --> -g i -h
|
||||
// g h i d e f d -f e
|
||||
Leap::Vector pointableFront = -pointable.direction();
|
||||
Leap::Vector pointableRight = Leap::Vector::up().cross(pointableFront);
|
||||
Leap::Vector pointableUp = pointableFront.cross(pointableRight);
|
||||
|
||||
outRotation.setColumn(0, Point4F( pointableRight.x, -pointableRight.z, pointableRight.y, 0.0f));
|
||||
outRotation.setColumn(1, Point4F( -pointableFront.x, pointableFront.z, -pointableFront.y, 0.0f));
|
||||
outRotation.setColumn(2, Point4F( pointableUp.x, -pointableUp.z, pointableUp.y, 0.0f));
|
||||
outRotation.setPosition(Point3F::Zero);
|
||||
}
|
||||
|
||||
}
|
||||
48
Engine/source/platform/input/leapMotion/leapMotionUtil.h
Normal file
48
Engine/source/platform/input/leapMotion/leapMotionUtil.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _LEAPMOTIONUTIL_H_
|
||||
#define _LEAPMOTIONUTIL_H_
|
||||
|
||||
#include "math/mPoint3.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "Leap.h"
|
||||
|
||||
namespace LeapMotionUtil
|
||||
{
|
||||
/// Convert from a Leap Motion position to a Torque 3D position
|
||||
void convertPosition(const Leap::Vector& inPosition, F32& x, F32& y, F32& z);
|
||||
|
||||
/// Convert from a Leap Motion position to a Torque 3D Point3F
|
||||
void convertPosition(const Leap::Vector& inPosition, Point3F& outPosition);
|
||||
|
||||
/// Convert a Leap Motion hand's rotation to a Torque 3D matrix
|
||||
void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation);
|
||||
|
||||
/// Calcualte a hand's rotation as if it were a thumb stick axis
|
||||
void calculateHandAxisRotation(const MatrixF& handRotation, const F32& maxHandAxisRadius, Point2F& outRotation);
|
||||
|
||||
/// Convert a Leap Motion pointable's rotation to a Torque 3D matrix
|
||||
void convertPointableRotation(const Leap::Pointable& pointable, MatrixF& outRotation);
|
||||
}
|
||||
|
||||
#endif
|
||||
79
Tools/projectGenerator/modules/leapMotion.inc
Normal file
79
Tools/projectGenerator/modules/leapMotion.inc
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
beginModule( 'leapMotion' );
|
||||
|
||||
// Look for the optional global from the project.conf.
|
||||
global $LEAPMOTION_SDK_PATH;
|
||||
if (!$LEAPMOTION_SDK_PATH)
|
||||
{
|
||||
// First look for an environment var.
|
||||
$LEAPMOTION_SDK_PATH = getenv( "TORQUE_LEAPMOTION_PATH" );
|
||||
|
||||
if (strlen($LEAPMOTION_SDK_PATH) == 0 || !file_exists($LEAPMOTION_SDK_PATH))
|
||||
{
|
||||
// Sometimes users get confused and use this var.
|
||||
$LEAPMOTION_SDK_PATH = getenv( "LEAPMOTION_SDK_PATH" );
|
||||
}
|
||||
|
||||
// We need forward slashes for paths.
|
||||
$LEAPMOTION_SDK_PATH = str_replace( "\\", "/", $LEAPMOTION_SDK_PATH);
|
||||
|
||||
// Remove trailing slashes.
|
||||
$LEAPMOTION_SDK_PATH = rtrim($LEAPMOTION_SDK_PATH, " /");
|
||||
}
|
||||
|
||||
// If we still don't have the SDK path then let the user know.
|
||||
if (!file_exists($LEAPMOTION_SDK_PATH))
|
||||
{
|
||||
trigger_error(
|
||||
"\n*******************************************************************".
|
||||
"\n".
|
||||
"\n We were not able to find a valid path to the Leap Motion SDK!".
|
||||
"\n".
|
||||
"\n You must install the latest Sixense SDK and set the path via a".
|
||||
"\n \$LEAPMOTION_SDK_PATH variable in your buildFiles/project.conf file".
|
||||
"\n or by setting the TORQUE_LEAPMOTION_PATH system environment variable".
|
||||
"\n (may require a reboot).".
|
||||
"\n".
|
||||
"\n*******************************************************************".
|
||||
"\n", E_USER_ERROR );
|
||||
}
|
||||
|
||||
// Only Windows is supported at this time
|
||||
if ( Generator::$platform == "win32" )
|
||||
{
|
||||
// Source
|
||||
addEngineSrcDir( "platform/input/leapMotion" );
|
||||
|
||||
// Includes
|
||||
addIncludePath( $LEAPMOTION_SDK_PATH . "/include" );
|
||||
|
||||
// Libs
|
||||
addProjectLibDir( $LEAPMOTION_SDK_PATH . "/lib/x86" );
|
||||
addProjectLibInput( "Leap.lib", "Leapd.lib" );
|
||||
}
|
||||
|
||||
endModule();
|
||||
|
||||
?>
|
||||
Loading…
Reference in a new issue