Ejemplo n.º 1
0
GestureFrame LMRecorder::prepareDataClone(const Leap::Frame frame, double timestamp)
{

	GestureFrame outputFrame;

	outputFrame.setTimestamp(timestamp);

	Leap::HandList handsInFrame = frame.hands();
	for(int handIndex=0; handIndex<handsInFrame.count(); handIndex++)
	{
		Leap::Hand currHand = handsInFrame[handIndex];

		//create GestureHand
		GestureHand gestureHand(
			currHand.id(),
			Vertex(currHand.palmPosition().x, currHand.palmPosition().y, currHand.palmPosition().z),
			Vertex(0, 0, 0/*currHand.stabilizedPalmPosition().x, currHand.stabilizedPalmPosition().y, currHand.stabilizedPalmPosition().z*/),
			Vertex(currHand.palmNormal().x, currHand.palmNormal().y, currHand.palmNormal().z),
			Vertex(currHand.direction().x, currHand.direction().y, currHand.direction().z)
		);
		gestureHand.setOrderValue(currHand.palmPosition().x);

		Vertex planeNormalVec = gestureHand.getDirection().crossProduct(gestureHand.getPalmNormal()).getNormalized();

		Leap::FingerList fingersInCurrHand = currHand.fingers();
		for (int fingerIndex=0; fingerIndex<fingersInCurrHand.count(); fingerIndex++)
		{
			Leap::Finger currFinger = fingersInCurrHand[fingerIndex];

			Leap::Vector leapFingerTipPos = currFinger.tipPosition();
			Vertex fingerTipPos(leapFingerTipPos.x, leapFingerTipPos.y, leapFingerTipPos.z);
			float distance = getPointDistanceFromPlane(fingerTipPos, gestureHand.getPalmPosition(), planeNormalVec);

			//create GestureFinger
			GestureFinger gestureFinger(
				currFinger.id(),
				fingerTipPos,
				Vertex(currFinger.stabilizedTipPosition().x, currFinger.stabilizedTipPosition().y, currFinger.stabilizedTipPosition(). z),
				Vertex(currFinger.direction().x, currFinger.direction().y, currFinger.direction().z),
				currFinger.length(),
				currFinger.width()
			);
			gestureFinger.setOrderValue(distance);

			gestureHand.addFinger(gestureFinger);
		}
		gestureHand.sortFingers();

		outputFrame.addHand(gestureHand);
	}
	outputFrame.sortHands();
}
// This controller mode just dumps out a bunch of the Leap Motion device data, which can then be
// analyzed for other use.
void LLLMImpl::modeDumpDebugInfo(Leap::HandList & hands)
{
	S32 numHands = hands.count();		
	if (numHands == 1)
	{
		// Get the first hand
		Leap::Hand hand = hands[0];

		// Check if the hand has any fingers
		Leap::FingerList finger_list = hand.fingers();
		S32 num_fingers = finger_list.count();

		if (num_fingers >= 1) 
		{	// Calculate the hand's average finger tip position
			Leap::Vector pos(0, 0, 0);
			Leap::Vector direction(0, 0, 0);
			for (size_t i = 0; i < num_fingers; ++i) 
			{
				Leap::Finger finger = finger_list[i];
				pos += finger.tipPosition();
				direction += finger.direction();

				// Lots of log spam
				LL_INFOS("LeapMotion") << "Finger " << i << " string is " << finger.toString() << LL_ENDL;
			}
			pos = Leap::Vector(pos.x/num_fingers, pos.y/num_fingers, pos.z/num_fingers);
			direction = Leap::Vector(direction.x/num_fingers, direction.y/num_fingers, direction.z/num_fingers);

			LL_INFOS("LeapMotion") << "Hand has " << num_fingers << " fingers with average tip position"
				<< " (" << pos.x << ", " << pos.y << ", " << pos.z << ")" 
				<< " direction (" << direction.x << ", " << direction.y << ", " << direction.z << ")" 
				<< LL_ENDL;

		}

		Leap::Vector palm_pos = hand.palmPosition();
		Leap::Vector palm_normal = hand.palmNormal();
		LL_INFOS("LeapMotion") << "Palm pos " << palm_pos.x
			<< ", " <<  palm_pos.y
			<< ", " <<  palm_pos.z
			<< ".   Normal: " << palm_normal.x
			<< ", " << palm_normal.y
			<< ", " << palm_normal.z
			<< LL_ENDL;

		F32 ball_radius = (F32) hand.sphereRadius();
		Leap::Vector ball_center = hand.sphereCenter();
		LL_INFOS("LeapMotion") << "Ball pos " << ball_center.x
			<< ", " << ball_center.y
			<< ", " << ball_center.z
			<< ", radius " << ball_radius
			<< LL_ENDL;
	}	// dump_out_data
}
Ejemplo n.º 3
0
void jester::LeapMotionImpl::setFingerInJointData(Leap::Finger finger, Bone::BoneId bone) {
	std::pair<Bone::JointId, Bone::JointId> joints = Bone::BoneToJointsMap.find(bone)->second;
	glm::vec3 fingerTip(finger.tipPosition()[0], finger.tipPosition()[1], finger.tipPosition()[2]);
	glm::vec3 fingerDir(finger.direction()[0], finger.direction()[1], finger.direction()[2]);
	float fingerLength = finger.length();
	JointFusionData fingerStartData;
	JointFusionData fingerEndData;

	fingerDir = glm::normalize(fingerDir);
	glm::vec3 fingerStart = fingerTip - fingerLength * fingerDir;

	glm::vec3 boneStart = glm::vec3(fingerStart / LeapMeasurmentScalingFactor);
	glm::vec3 boneEnd = glm::vec3(fingerTip / LeapMeasurmentScalingFactor);
	fingerStartData.position = boneStart;
	fingerEndData.position = boneEnd;
	fingerStartData.id = joints.first;
	fingerEndData.id = joints.second;
	fingerStartData.confidence = fingerEndData.confidence = LeapConfidence;

	kJointData.insert(std::pair<Bone::JointId, JointFusionData>(joints.first, fingerStartData));
	kJointData.insert(std::pair<Bone::JointId, JointFusionData>(joints.second, fingerEndData));
}
// This mode tries to detect simple hand motion and either triggers an avatar gesture or 
// sends a chat message into SL in response.   It is very rough, hard-coded for detecting 
// a hand wave (a SL gesture) or the wiggling-thumb gun trigger (a chat message sent to a
// special version of the popgun).
void LLLMImpl::modeGestureDetection1(Leap::HandList & hands)
{
	static S32 trigger_direction = -1;

	S32 numHands = hands.count();
	if (numHands == 1)
	{
		// Get the first hand
		Leap::Hand hand = hands[0];

		// Check if the hand has any fingers
		Leap::FingerList finger_list = hand.fingers();
		S32 num_fingers = finger_list.count();
		static S32 last_num_fingers = 0;

		if (num_fingers == 1)
		{	// One finger ... possibly reset the 
			Leap::Finger finger = finger_list[0];
			Leap::Vector finger_dir = finger.direction();

			// Negative Z is into the screen - check that it's the largest component
			S32 abs_z_dir = llabs(finger_dir.z);
			if (finger_dir.z < -0.5 &&
				abs_z_dir > llabs(finger_dir.x) &&
				abs_z_dir > llabs(finger_dir.y))
			{
				Leap::Vector finger_pos = finger.tipPosition();
				Leap::Vector finger_vel = finger.tipVelocity(); 
				LL_INFOS("LeapMotion") << "finger direction is " << finger_dir.x << ", " << finger_dir.y << ", " << finger_dir.z
					<< ", position " << finger_pos.x << ", " << finger_pos.y << ", " << finger_pos.z 
					<< ", velocity " << finger_vel.x << ", " << finger_vel.y << ", " << finger_vel.z 
					<< LL_ENDL;
			}

			if (trigger_direction != -1)
			{
				LL_INFOS("LeapMotion") << "Reset trigger_direction - one finger" << LL_ENDL;
				trigger_direction = -1;
			}
		}
		else if (num_fingers == 2)
		{
			Leap::Finger barrel_finger = finger_list[0];
			Leap::Vector barrel_finger_dir = barrel_finger.direction();

			// Negative Z is into the screen - check that it's the largest component
			F32 abs_z_dir = llabs(barrel_finger_dir.z);
			if (barrel_finger_dir.z < -0.5f &&
				abs_z_dir > llabs(barrel_finger_dir.x) &&
				abs_z_dir > llabs(barrel_finger_dir.y))
			{
				Leap::Finger thumb_finger = finger_list[1];
				Leap::Vector thumb_finger_dir = thumb_finger.direction();
				Leap::Vector thumb_finger_pos = thumb_finger.tipPosition();
				Leap::Vector thumb_finger_vel = thumb_finger.tipVelocity();

				if ((thumb_finger_dir.x < barrel_finger_dir.x) )
				{	// Trigger gunfire
					if (trigger_direction < 0 &&		// Haven't fired
						thumb_finger_vel.x > 50.f &&	// Moving into screen
						thumb_finger_vel.z < -50.f &&
						mChatMsgTimer.checkExpirationAndReset(LLLEAP_CHAT_MSG_INTERVAL))
					{
						// Chat message looks like "/2343 LM2 gunfire"
						std::string gesture_chat_msg("/2343 LM2 gunfire");
						//LLNearbyChatBar::sendChatFromViewer(gesture_chat_msg, CHAT_TYPE_SHOUT, FALSE);
						trigger_direction = 1;
						LL_INFOS("LeapMotion") << "Sent gunfire chat" << LL_ENDL;
					}
					else if (trigger_direction > 0 &&	// Have fired, need to pull thumb back
						thumb_finger_vel.x < -50.f &&
						thumb_finger_vel.z > 50.f)		// Moving out of screen
					{
						trigger_direction = -1;
						LL_INFOS("LeapMotion") << "Reset trigger_direction" << LL_ENDL;
					}
				}
			}
			else if (trigger_direction != -1)
			{
				LL_INFOS("LeapMotion") << "Reset trigger_direction - hand pos" << LL_ENDL;
				trigger_direction = -1;
			}
		}
		else if (num_fingers == 5 &&
			num_fingers == last_num_fingers)
		{
			if (mGestureTimer.checkExpirationAndReset(LLLEAP_GESTURE_INTERVAL))
			{
				// figure out a gesture to trigger
				std::string gestureString("/overhere");
				LLGestureMgr::instance().triggerAndReviseString( gestureString );
			}
		}
		
		last_num_fingers = num_fingers;
	}
}
Ejemplo n.º 5
0
void LeapManager::nextFrame(Avatar& avatar) {
    // Apply the frame data directly to the avatar.
    Hand& hand = avatar.getHand();
    
    // If we actually get valid Leap data, this will be set to true;
    bool gotRealData = false;

    if (controllersExist()) {
        _listener->onFrame(*_controller);
    }

#ifndef LEAP_STUBS
    if (controllersExist()) {
        gotRealData = true;
        // First, see which palms and fingers are still valid.
        Leap::Frame& frame = _listener->lastFrame;
        
        // Note that this is O(n^2) at worst, but n is very small.

        // After this many frames of no data, assume the digit is lost.
        const int assumeLostAfterFrameCount = 10;

        // Increment our frame data counters
        for (size_t i = 0; i < hand.getNumPalms(); ++i) {
            PalmData& palm = hand.getPalms()[i];
            palm.incrementFramesWithoutData();
            if (palm.getFramesWithoutData() > assumeLostAfterFrameCount) {
                palm.setActive(false);
            }
            for (size_t f = 0; f < palm.getNumFingers(); ++f) {
                FingerData& finger = palm.getFingers()[f];
                finger.incrementFramesWithoutData();
                if (finger.getFramesWithoutData() > assumeLostAfterFrameCount) {
                    finger.setActive(false);
                }
            }
        }

        size_t numLeapHands = frame.hands().count();
        std::vector<PalmData*> palmAssignment(numLeapHands);
        
        // Look for matches
        for (size_t index = 0; index < numLeapHands; ++index) {
            PalmData* takeoverCandidate = NULL;
            palmAssignment[index] = NULL;
            Leap::Hand leapHand = frame.hands()[index];
            int id = leapHand.id();
            if (leapHand.isValid()) {
                for (size_t i = 0; i < hand.getNumPalms() && palmAssignment[index] == NULL; ++i) {
                    PalmData& palm = hand.getPalms()[i];
                    if (palm.getLeapID() == id) {
                        // Found hand with the same ID. We're set!
                        palmAssignment[index] = &palm;
                        palm.resetFramesWithoutData();
                    }
                    else if (palm.getFramesWithoutData() > assumeLostAfterFrameCount) {
                        takeoverCandidate = &palm;
                    }
                }
                if (palmAssignment[index] == NULL) {
                    palmAssignment[index] = takeoverCandidate;
                }
                if (palmAssignment[index] == NULL) {
                    palmAssignment[index] = &hand.addNewPalm();
                }
            }
        }
        
        // Apply the assignments
        for (size_t index = 0; index < numLeapHands; ++index) {
            if (palmAssignment[index]) {
                Leap::Hand leapHand = frame.hands()[index];
                PalmData& palm = *(palmAssignment[index]);

                palm.resetFramesWithoutData();
                palm.setLeapID(leapHand.id());
                palm.setActive(true);
                const Leap::Vector pos = leapHand.palmPosition();
                const Leap::Vector normal = leapHand.palmNormal();
                palm.setRawPosition(glm::vec3(pos.x, pos.y, pos.z));
                palm.setRawNormal(glm::vec3(normal.x, normal.y, normal.z));
            }
        }

        // Look for fingers per palm
        for (size_t i = 0; i < hand.getNumPalms(); ++i) {
            PalmData& palm = hand.getPalms()[i];
            if (palm.isActive()) {
                Leap::Hand leapHand = frame.hand(palm.getLeapID());
                if (leapHand.isValid()) {
                    int numLeapFingers = leapHand.fingers().count();
                    std::vector<FingerData*> fingerAssignment(numLeapFingers);

                    
                    // Look for matches
                    for (size_t index = 0; index < numLeapFingers; ++index) {
                        FingerData* takeoverCandidate = NULL;
                        fingerAssignment[index] = NULL;
                        Leap::Finger leapFinger = leapHand.fingers()[index];
                        int id = leapFinger.id();
                        if (leapFinger.isValid()) {
                            for (size_t f = 0; f < palm.getNumFingers() && fingerAssignment[index] == NULL; ++f) {
                                FingerData& finger = palm.getFingers()[f];
                                if (finger.getLeapID() == id) {
                                    // Found hand with the same ID. We're set!
                                    fingerAssignment[index] = &finger;
                                }
                                else if (finger.getFramesWithoutData() > assumeLostAfterFrameCount) {
                                    takeoverCandidate = &finger;
                                }
                            }
                            // If we didn't find a match, but we found an unused finger, us it.
                            if (fingerAssignment[index] == NULL) {
                                fingerAssignment[index] = takeoverCandidate;
                            }
                        }
                    }

                    // Apply the assignments
                    for (size_t index = 0; index < numLeapFingers; ++index) {
                        if (fingerAssignment[index]) {
                            Leap::Finger leapFinger = leapHand.fingers()[index];
                            FingerData& finger = *(fingerAssignment[index]);
                            
                            finger.resetFramesWithoutData();
                            finger.setLeapID(leapFinger.id());
                            finger.setActive(true);
#ifdef USE_STABILIZED_DATA
                            const Leap::Vector tip = leapFinger.stabilizedTipPosition();
#else
                            const Leap::Vector tip = leapFinger.tipPosition();
#endif
                            const Leap::Vector root = tip - leapFinger.direction() * leapFinger.length();
                            finger.setRawTipPosition(glm::vec3(tip.x, tip.y, tip.z));
                            finger.setRawRootPosition(glm::vec3(root.x, root.y, root.z));
                        }
                    }
                }
            }
        }
    }
#endif
    if (!gotRealData) {
        if (_doFakeFingers) {
            // There's no real Leap data and we need to fake it.
            for (size_t i = 0; i < hand.getNumPalms(); ++i) {
                static const glm::vec3 fakeHandOffsets[] = {
                    glm::vec3( -500.0f, 50.0f, 50.0f),
                    glm::vec3(    0.0f, 50.0f, 50.0f)
                };
                static const glm::vec3 fakeHandFingerMirrors[] = {
                    glm::vec3( -1.0f, 1.0f, 1.0f),
                    glm::vec3(  1.0f, 1.0f, 1.0f)
                };
                static const glm::vec3 fakeFingerPositions[] = {
                    glm::vec3( -60.0f, 0.0f, -40.0f),
                    glm::vec3( -20.0f, 0.0f, -60.0f),
                    glm::vec3(  20.0f, 0.0f, -60.0f),
                    glm::vec3(  60.0f, 0.0f, -40.0f),
                    glm::vec3( -50.0f, 0.0f,  30.0f)
                };

                PalmData& palm = hand.getPalms()[i];
                palm.setActive(true);
                // Simulated data
                
                palm.setRawPosition(glm::vec3( 0.0f, 0.0f, 0.0f) + fakeHandOffsets[i]);
                palm.setRawNormal(glm::vec3(0.0f, 1.0f, 0.0f));

                for (size_t f = 0; f < palm.getNumFingers(); ++f) {
                    FingerData& finger = palm.getFingers()[f];
                    finger.setActive(true);
                    const float tipScale = 1.5f;
                    const float rootScale = 0.75f;
                    glm::vec3 fingerPos = fakeFingerPositions[f] * fakeHandFingerMirrors[i];
                    finger.setRawTipPosition(fingerPos * tipScale + fakeHandOffsets[i]);
                    finger.setRawRootPosition(fingerPos * rootScale + fakeHandOffsets[i]);
                }
            }
        }
        else {
            // Just deactivate everything.
            for (size_t i = 0; i < hand.getNumPalms(); ++i) {
                PalmData& palm = hand.getPalms()[i];
                palm.setActive(false);
                for (size_t f = 0; f < palm.getNumFingers(); ++f) {
                    FingerData& finger = palm.getFingers()[f];
                    finger.setActive(false);
                }
            }
        }
    }
    hand.updateFingerTrails();
}