static VALUE tip_position(VALUE self) { Leap::Pointable * pointer; Leap::Vector * vector; Data_Get_Struct(self, Leap::Pointable, pointer); vector = new Leap::Vector(pointer->tipPosition()); return WrapVector(vector); }
void ZirkLeap::onFrame(const Leap::Controller& controller) { if(controller.hasFocus()) { Leap::Frame frame = controller.frame(); if (mPointableId >= 0) { ourProcessor->setSelectedSource(mEditor->getCBSelectedSource()-1); Leap::Pointable p = frame.pointable(mPointableId); if (!p.isValid() || !p.isExtended()) { mPointableId = -1; mLastPositionValid = false; } else { Leap::Vector pos = p.tipPosition(); const float zPlane1 = 50; // 5 cm const float zPlane2 = 100; // 10 cm if (pos.z < zPlane2) { if (mLastPositionValid) { //Leap Motion mouvement are calculated from the last position in order to have something dynamic and ergonomic Leap::Vector delta = pos- mLastPosition; float scale = 3; if (pos.z > zPlane1) { float s = 1 - (pos.z - zPlane1) / (zPlane2 - zPlane1); scale *= s; } int src = ourProcessor->getSelectedSource(); float fX, fY; ourProcessor->getSources()[src].getXY(fX, fY); fX += delta.x * scale; fY -= delta.y * scale; //clamp coordinates to circle float fCurR = hypotf(fX, fY); if ( fCurR > ZirkOscAudioProcessor::s_iDomeRadius){ float fExtraRatio = ZirkOscAudioProcessor::s_iDomeRadius / fCurR; fX *= fExtraRatio; fY *= fExtraRatio; } mEditor->move(src, fX, fY); } else { //std::cout << "pointable last pos not valid" << std::endl; } mLastPosition = pos; mLastPositionValid = true; } else { //std::cout << "pointable not touching plane" << std::endl; mLastPositionValid = false; } } } if (mPointableId < 0) { Leap::PointableList pl = frame.pointables().extended(); if (pl.count() > 0) { mPointableId = pl[0].id(); //std::cout << "got new pointable: " << mPointableId << std::endl; } } } }
void Scene::updateInteraction( const Frame& frame ) { static const uint8_t kMaxContactMissedFrames = 64; (void)frame; for (size_t i=0; i < m_uiNumObjects; i++) { const SceneObjectPtr& pObj = m_apObjects[i]; if (!pObj->HasInitialContact() && pObj->GetNumContacts() == 0 && pObj->GetNumPointing() == 0) { pObj->m_fTotalHitTime = 0.0f; } /// selection state change from not selected to selected else if ( !pObj->IsSelected() && pObj->m_fTotalHitTime >= m_fSelectHitTime ) { SceneInteraction selection; selection.m_uiFlags = kIT_SelectionChange | kIT_IsSelected; selection.m_pObject = pObj; queueInteraction( selection ); } /// possible manipulation else if ( pObj->IsSelected() ) { if ( pObj->HasInitialContact() ) { const SceneContactPoint& initContact = pObj->m_initialContactPoint; Leap::Pointable contactPointable = frame.pointable(initContact.m_iPointableID); if ( contactPointable.isValid() ) { const Vector vPointablePos = TransformFramePoint(contactPointable.tipPosition()); const Vector vTrans = (vPointablePos - pObj->GetCenter()); SceneInteraction translation; translation.m_mtxTransform.origin = vTrans; translation.m_uiFlags |= kIT_Translation; translation.m_pObject = pObj; queueInteraction( translation ); pObj->m_uiHasInitialContact = kMaxContactMissedFrames; } else { pObj->m_uiHasInitialContact--; if ( !pObj->m_uiLastNumContacts ) { pObj->ClearHits(); } } } else { if ( pObj->GetNumContacts() ) { pObj->m_initialContactPoint = *(pObj->GetContactPoint(0)); pObj->m_initialContactPoint.m_vPoint -= pObj->GetCenter(); pObj->m_uiHasInitialContact = kMaxContactMissedFrames; } else if ( pObj->GetLastNumContacts() ) { pObj->m_initialContactPoint = *(pObj->GetLastContactPoint(0)); pObj->m_initialContactPoint.m_vPoint -= pObj->GetCenter(); pObj->m_uiHasInitialContact = kMaxContactMissedFrames; } } /// multi touch if (pObj->GetLastNumContacts() >= 2 && pObj->GetNumContacts() >= 2) { const SceneContactPoint& lastContact0 = *(pObj->GetLastContactPoint(0)); const SceneContactPoint& lastContact1 = *(pObj->GetLastContactPoint(1)); const SceneContactPoint* pCurContact0 = pObj->GetContactPointByPointableID( lastContact0.m_iPointableID ); const SceneContactPoint* pCurContact1 = pObj->GetContactPointByPointableID( lastContact1.m_iPointableID ); if ( pCurContact0 && pCurContact1 ) { const Vector lastVec = (lastContact1.m_vPoint - lastContact0.m_vPoint); const Vector newVec = (pCurContact1->m_vPoint - pCurContact0->m_vPoint); if ( !IsNearEqual(lastVec, newVec) && !IsNearZero(lastVec) ) { const float fLastDist = lastVec.magnitude(); const float fNewDist = newVec.magnitude(); /// scale by change in pinch distance const float fScale = fNewDist/fLastDist; /// rotate by tilt of fingers const Vector vLastDir = lastVec * 1.0f/fLastDist; const Vector vNewDir = newVec * 1.0f/fNewDist; const Vector vAxis = vNewDir.cross(vLastDir); const float fAngle = acosf( vNewDir.dot(vLastDir) ); /// translate by average movement const Vector vTrans = ( (pCurContact0->m_vPoint - lastContact0.m_vPoint) + (pCurContact1->m_vPoint - lastContact1.m_vPoint) ) * 0.5f; SceneInteraction interaction; if ( !IsNearZero(fAngle) ) { interaction.m_mtxTransform.setRotation( vAxis, fAngle ); interaction.m_uiFlags |= kIT_Rotation; } if ( !IsNearEqual(fScale, 1.0f) ) { interaction.m_fScale = fScale; interaction.m_uiFlags |= kIT_Scale; } if ( !IsNearZero( vTrans ) ) { interaction.m_mtxTransform.origin = vTrans; interaction.m_uiFlags |= kIT_Translation; } if ( interaction.m_uiFlags ) { interaction.m_pObject = pObj; queueInteraction( interaction ); } } } } } pObj->rotateContactPoints(); pObj->m_uiNumPointing = 0; } }