void ObjectDetector::RegisterObject( ObjectDetectorLink& iLink, HOBJECT hObject, void* pUserData ) { // Make sure it isn't registered somewhere else first... ReleaseLink( iLink ); // Make sure the object is valid if( !hObject ) { return; } // Assign the new object and detector iLink.m_hObject = hObject; iLink.m_pDetector = this; iLink.m_pUserData = pUserData; ++m_nRegisteredObjects; // Now hook it up to the root link... iLink.m_pPrev = &m_iRootLink; iLink.m_pNext = m_iRootLink.m_pNext; if( m_iRootLink.m_pNext ) { m_iRootLink.m_pNext->m_pPrev = &iLink; } m_iRootLink.m_pNext = &iLink; }
// Stop all links void StopAllLink(HUB *h) { LINK **link_list; UINT num_link; UINT i; // Validate arguments if (h == NULL) { return; } LockList(h->LinkList); { link_list = ToArray(h->LinkList); num_link = LIST_NUM(h->LinkList); for (i = 0;i < num_link;i++) { AddRef(link_list[i]->ref); } } UnlockList(h->LinkList); for (i = 0;i < num_link;i++) { StopLink(link_list[i]); ReleaseLink(link_list[i]); } Free(link_list); }
// Release all links void ReleaseAllLink(HUB *h) { LINK **kk; UINT num, i; // Validate arguments if (h == NULL) { return; } LockList(h->LinkList); { num = LIST_NUM(h->LinkList); kk = ToArray(h->LinkList); DeleteAll(h->LinkList); } UnlockList(h->LinkList); for (i = 0;i < num;i++) { LINK *k = kk[i]; ReleaseLink(k); } Free(kk); }
ObjectDetector::~ObjectDetector() { // Detach all the links while( m_iRootLink.m_pNext ) { ReleaseLink( *m_iRootLink.m_pNext ); } }
// Delete the link void DelLink(HUB *hub, LINK *k) { // Validate arguments if (hub == NULL || k == NULL) { return; } LockList(hub->LinkList); { if (Delete(hub->LinkList, k)) { ReleaseLink(k); } } UnlockList(hub->LinkList); }
// リンクの削除 void DelLink(HUB *hub, LINK *k) { // 引数チェック if (hub == NULL || k == NULL) { return; } LockList(hub->LinkList); { if (Delete(hub->LinkList, k)) { ReleaseLink(k); } } UnlockList(hub->LinkList); }
HOBJECT ObjectDetector::AcquireObject( bool bFromPrevious ) { // Make sure the object to the currently tracked link is still valid if( m_pTrackedLink && !m_pTrackedLink->m_hObject.GetData() ) { ReleaseLink( *m_pTrackedLink ); ClearObject(); } // If we don't have any acquire flags set... then don't do anything if( !( m_nBehaviorFlags & ODBF_ACQUIREMASK ) ) { return NULL; } // Keep track of the links that fit the previous, best, and current requirements ObjectDetectorLink* pPrevTracked = ( bFromPrevious ? m_pTrackedLink : NULL ); ObjectDetectorLink* pCurrTracked = NULL; ObjectDetectorLink* pBestTracked = NULL; // Requirement ranges and other data tracking variables float fPrevRR = 0.0f; float fCurrRR = 1000000.0f; float fBestRR = 1000000.0f; float fTempRR, fActiveRR; uint32 nAttemptedTests, nPassedTests; bool bContinue; // Get the previously tracked link data... add up the RR values even if the // tests don't pass. This way we get a relative value to compare to regardless // of whether it can be acquired again during this attempt. if( pPrevTracked ) { LTVector vPos, vDims; GetObjectSpatialData( pPrevTracked, vPos, vDims ); if( m_nBehaviorFlags & ODBF_ACQUIREFORWARD ) { TestParamsForward( pPrevTracked, vPos, vDims, fTempRR ); fPrevRR += fTempRR; } if( m_nBehaviorFlags & ODBF_ACQUIREDIRECTION ) { TestParamsDirection( pPrevTracked, vPos, vDims, fTempRR ); fPrevRR += fTempRR; } if( m_nBehaviorFlags & ODBF_ACQUIREFOV ) { TestParamsFOV( pPrevTracked, vPos, vDims, fTempRR ); fPrevRR += fTempRR; } if( m_nBehaviorFlags & ODBF_ACQUIRESPHERE ) { TestParamsSphere( pPrevTracked, vPos, vDims, fTempRR ); fPrevRR += fTempRR; } if( m_nBehaviorFlags & ODBF_ACQUIRECYLINDER ) { TestParamsCylinder( pPrevTracked, vPos, vDims, fTempRR ); fPrevRR += fTempRR; } if( m_nBehaviorFlags & ODBF_ACQUIRECUSTOM ) { TestParamsCustom( pPrevTracked, fTempRR ); fPrevRR += fTempRR; } } // Go through each registered object ObjectDetectorLink* pLink = m_iRootLink.m_pNext; while( pLink ) { LTVector vPos, vDims; GetObjectSpatialData( pLink, vPos, vDims ); // Ignore the previous tracked link if( pLink == pPrevTracked ) { pLink = pLink->m_pNext; continue; } // If this link has invalid object data... release it if( !pLink->m_hObject.GetData() ) { ObjectDetectorLink* pRemove = pLink; pLink = pLink->m_pNext; ReleaseLink( *pRemove ); continue; } // Check our user flag verification if( m_nUserFlagVerification ) { uint32 nUserFlags; g_pLTClient->Common()->GetObjectFlags( pLink->m_hObject, OFT_User, nUserFlags ); if( ( nUserFlags & m_nUserFlagVerification ) != m_nUserFlagVerification ) { continue; } } // Zero out our temporary requirement range fActiveRR = 0.0f; nAttemptedTests = 0; nPassedTests = 0; // Check all the necessary params if( m_nBehaviorFlags & ODBF_ACQUIREFORWARD ) { ++nAttemptedTests; if( TestParamsForward( pLink, vPos, vDims, fTempRR ) ) { fActiveRR += fTempRR; ++nPassedTests; } } if( m_nBehaviorFlags & ODBF_ACQUIREDIRECTION ) { ++nAttemptedTests; if( TestParamsDirection( pLink, vPos, vDims, fTempRR ) ) { fActiveRR += fTempRR; ++nPassedTests; } } if( m_nBehaviorFlags & ODBF_ACQUIREFOV ) { ++nAttemptedTests; if( TestParamsFOV( pLink, vPos, vDims, fTempRR ) ) { fActiveRR += fTempRR; ++nPassedTests; } } if( m_nBehaviorFlags & ODBF_ACQUIRESPHERE ) { ++nAttemptedTests; if( TestParamsSphere( pLink, vPos, vDims, fTempRR ) ) { fActiveRR += fTempRR; ++nPassedTests; } } if( m_nBehaviorFlags & ODBF_ACQUIRECYLINDER ) { ++nAttemptedTests; if( TestParamsCylinder( pLink, vPos, vDims, fTempRR ) ) { fActiveRR += fTempRR; ++nPassedTests; } } if( m_nBehaviorFlags & ODBF_ACQUIRECUSTOM ) { ++nAttemptedTests; if( TestParamsCustom( pLink, fTempRR ) ) { fActiveRR += fTempRR; ++nPassedTests; } } // Make sure we passed the required tests... if( m_nBehaviorFlags & ODBF_INCLUSIVEACQUIRE ) { bContinue = ( nPassedTests == nAttemptedTests ); } else { bContinue = ( nPassedTests > 0 ); } if( bContinue ) { // Make sure we have a line of site to this object if( m_nBehaviorFlags & ODBF_ACQUIRELINEOFSITE ) { bContinue = TestLineOfSite( pLink ); } // If we passed the line of site test... if( bContinue ) { // If the active test is better than our best... track it! if( fActiveRR < fBestRR ) { fBestRR = fActiveRR; pBestTracked = pLink; } // If the active test is after our previous, but better than the current... track it too! if( ( fActiveRR > fPrevRR ) && ( fActiveRR < fCurrRR ) ) { fCurrRR = fActiveRR; pCurrTracked = pLink; } } } // Move on to the next object pLink = pLink->m_pNext; } // Reset our verification timers memcpy( m_fActiveVerifyFailureDelays, m_fVerifyFailureDelays, sizeof( float ) * ODBF_TESTSAVAILABLE ); // Set our tracked link to the proper one if( pCurrTracked ) { SetLink( pCurrTracked ); } else if( pBestTracked ) { SetLink( pBestTracked ); } else if( !pPrevTracked ) { ClearObject(); } return GetObject(); }
void ObjectDetector::Update( float fFrameTime ) { // If we don't have a tracked link... there's nothing to update! if( !m_pTrackedLink ) { return; } // Make sure the link is still valid if( !m_pTrackedLink->m_hObject.GetData() ) { ReleaseLink( *m_pTrackedLink ); ClearObject(); return; } // If we don't have any verify flags set... then don't do anything if( !( m_nBehaviorFlags & ODBF_VERIFYMASK ) ) { return; } // Requirement ranges and other data tracking variables float fTempRR; uint32 nAttemptedTests = 0; uint32 nPassedTests = 0; UpdateObjectSpatialData(); // Handle each verification type if( m_nBehaviorFlags & ODBF_VERIFYLINEOFSITE ) { ++nAttemptedTests; if( TestLineOfSite( m_pTrackedLink ) ) { m_fActiveVerifyFailureDelays[ 0 ] = m_fVerifyFailureDelays[ 0 ]; ++nPassedTests; } else { if( m_fActiveVerifyFailureDelays[ 0 ] > 0.0f ) { m_fActiveVerifyFailureDelays[ 0 ] -= fFrameTime; ++nPassedTests; } } } if( m_nBehaviorFlags & ODBF_VERIFYFORWARD ) { ++nAttemptedTests; if( TestParamsForward( m_pTrackedLink, m_vTrackedSpatialPosition, m_vTrackedSpatialDimensions, fTempRR ) ) { m_fActiveVerifyFailureDelays[ 1 ] = m_fVerifyFailureDelays[ 1 ]; ++nPassedTests; } else { if( m_fActiveVerifyFailureDelays[ 1 ] > 0.0f ) { m_fActiveVerifyFailureDelays[ 1 ] -= fFrameTime; ++nPassedTests; } } } if( m_nBehaviorFlags & ODBF_VERIFYDIRECTION ) { ++nAttemptedTests; if( TestParamsDirection( m_pTrackedLink, m_vTrackedSpatialPosition, m_vTrackedSpatialDimensions, fTempRR ) ) { m_fActiveVerifyFailureDelays[ 2 ] = m_fVerifyFailureDelays[ 2 ]; ++nPassedTests; } else { if( m_fActiveVerifyFailureDelays[ 2 ] > 0.0f ) { m_fActiveVerifyFailureDelays[ 2 ] -= fFrameTime; ++nPassedTests; } } } if( m_nBehaviorFlags & ODBF_VERIFYFOV ) { ++nAttemptedTests; if( TestParamsFOV( m_pTrackedLink, m_vTrackedSpatialPosition, m_vTrackedSpatialDimensions, fTempRR ) ) { m_fActiveVerifyFailureDelays[ 3 ] = m_fVerifyFailureDelays[ 3 ]; ++nPassedTests; } else { if( m_fActiveVerifyFailureDelays[ 3 ] > 0.0f ) { m_fActiveVerifyFailureDelays[ 3 ] -= fFrameTime; ++nPassedTests; } } } if( m_nBehaviorFlags & ODBF_VERIFYSPHERE ) { ++nAttemptedTests; if( TestParamsSphere( m_pTrackedLink, m_vTrackedSpatialPosition, m_vTrackedSpatialDimensions, fTempRR ) ) { m_fActiveVerifyFailureDelays[ 4 ] = m_fVerifyFailureDelays[ 4 ]; ++nPassedTests; } else { if( m_fActiveVerifyFailureDelays[ 4 ] > 0.0f ) { m_fActiveVerifyFailureDelays[ 4 ] -= fFrameTime; ++nPassedTests; } } } if( m_nBehaviorFlags & ODBF_VERIFYCYLINDER ) { ++nAttemptedTests; if( TestParamsCylinder( m_pTrackedLink, m_vTrackedSpatialPosition, m_vTrackedSpatialDimensions, fTempRR ) ) { m_fActiveVerifyFailureDelays[ 5 ] = m_fVerifyFailureDelays[ 5 ]; ++nPassedTests; } else { if( m_fActiveVerifyFailureDelays[ 5 ] > 0.0f ) { m_fActiveVerifyFailureDelays[ 5 ] -= fFrameTime; ++nPassedTests; } } } if( m_nBehaviorFlags & ODBF_VERIFYCUSTOM ) { ++nAttemptedTests; if( TestParamsCustom( m_pTrackedLink, fTempRR ) ) { m_fActiveVerifyFailureDelays[ 6 ] = m_fVerifyFailureDelays[ 6 ]; ++nPassedTests; } else { if( m_fActiveVerifyFailureDelays[ 6 ] > 0.0f ) { m_fActiveVerifyFailureDelays[ 6 ] -= fFrameTime; ++nPassedTests; } } } // Make sure we passed the required tests... if( ( nPassedTests == 0 ) || ( ( m_nBehaviorFlags & ODBF_INCLUSIVEVERIFY ) && ( nPassedTests != nAttemptedTests ) ) ) { ClearObject(); } // Otherwise, see if we're in a delay for clearing the object... and apply that instead if( m_fActiveClearDelay != OD_INVALID_CLEAR_DELAY ) { m_fActiveClearDelay -= fFrameTime; if( m_fActiveClearDelay <= 0.0f ) { ClearObject(); } } }