123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- //-----------------------------------------------------------------------------
- // 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;
- }
|