diff options
Diffstat (limited to 'movieobjects/dmeselection.cpp')
| -rw-r--r-- | movieobjects/dmeselection.cpp | 577 |
1 files changed, 577 insertions, 0 deletions
diff --git a/movieobjects/dmeselection.cpp b/movieobjects/dmeselection.cpp new file mode 100644 index 0000000..7528f88 --- /dev/null +++ b/movieobjects/dmeselection.cpp @@ -0,0 +1,577 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + + +#include "datamodel/dmelementfactoryhelper.h" +#include "movieobjects/dmeselection.h" + + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Expose this class to the scene database +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeComponent, CDmeComponent ); + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeComponent::OnConstruction() +{ + m_Type.InitAndSet( this, "componentType", COMP_INVALID ); + m_bComplete.InitAndSet( this, "complete", false ); +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeComponent::OnDestruction() +{ +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeComponent::Resolve() +{ +} + + +//----------------------------------------------------------------------------- +// Expose this class to the scene database +//----------------------------------------------------------------------------- +IMPLEMENT_ELEMENT_FACTORY( DmeSingleIndexedComponent, CDmeSingleIndexedComponent ); + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::OnConstruction() +{ + m_CompleteCount.InitAndSet( this, "completeCount", 0 ); + m_Components.Init( this, "components" ); + m_Weights.Init( this, "weights" ); +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::OnDestruction() +{ +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::Resolve() +{ +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +int CDmeSingleIndexedComponent::Count() const +{ + return IsComplete() ? m_CompleteCount.Get() : m_Components.Count(); +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CDmeSingleIndexedComponent::SetType( Component_t type ) +{ + switch ( type ) + { + case COMP_VTX: + case COMP_FACE: + m_Type.Set( type ); + return true; + default: + break; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::AddComponent( int component, float weight /*= 1.0f */ ) +{ + if ( IsComplete() ) + return; + + const int index( BinarySearch( component ) ); + Assert( index >= 0 ); + Assert( index <= m_Components.Count() ); + if ( index == m_Components.Count() ) + { + m_Components.AddToTail( component ); + m_Weights.AddToTail( weight ); + } + else if ( component == m_Components.Get( index ) ) + { + Assert( index < m_Weights.Count() ); + m_Weights.Set( index, weight ); + } + else + { + m_Components.InsertBefore( index, component ); + m_Weights.InsertBefore( index, weight ); + } +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::AddComponents( const CUtlVector< int > &components ) +{ + const int nComponents( components.Count() ); + for ( int i( 0 ); i < nComponents; ++i ) + { + AddComponent( components[ i ] ); + } +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::AddComponents( + const CUtlVector< int > &components, const CUtlVector< float > &weights ) +{ + const int nComponents( min( components.Count(), weights.Count() ) ); + for ( int i( 0 ); i < nComponents; ++i ) + { + AddComponent( components[ i ], weights[ i ] ); + } +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::RemoveComponent( int component ) +{ + Assert( !IsComplete() ); // TODO: Convert from complete to complete - component + + const int cIndex = BinarySearch( component ); + if ( cIndex >= m_Components.Count() || m_Components[ cIndex ] != component ) // Component not in selection + return; + + m_Components.Remove( cIndex ); + m_Weights.Remove( cIndex ); +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CDmeSingleIndexedComponent::GetComponent( int index, int &component, float &weight ) const +{ + if ( index < Count() ) + { + if ( IsComplete() ) + { + component = index; + weight = 1.0f; + } + else + { + component = m_Components[ index ]; + weight = m_Weights[ index ]; + } + + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::GetComponents( CUtlVector< int > &components, CUtlVector< float > &weights ) const +{ + if ( IsComplete() ) + { + const int nComponents = Count(); + + int *pComponents = reinterpret_cast< int * >( alloca( nComponents * sizeof( int ) ) ); + float *pWeights = reinterpret_cast< float * >( alloca( nComponents * sizeof( float ) ) ); + + for ( int i = 0; i < nComponents; ++i ) + { + pComponents[ i ] = i; + pWeights[ i ] = 1.0f; + } + + components.CopyArray( pComponents, nComponents ); + weights.CopyArray( pWeights, nComponents ); + } + else + { + components.RemoveAll(); + components.CopyArray( m_Components.Base(), m_Components.Count() ); + + weights.RemoveAll(); + weights.CopyArray( m_Weights.Base(), m_Weights.Count() ); + } +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::GetComponents( CUtlVector< int > &components ) const +{ + if ( IsComplete() ) + { + const int nComponents = Count(); + + int *pComponents = reinterpret_cast< int * >( alloca( nComponents * sizeof( int ) ) ); + + for ( int i = 0; i < nComponents; ++i ) + { + pComponents[ i ] = i; + } + + components.CopyArray( pComponents, nComponents ); + } + else + { + components.RemoveAll(); + components.CopyArray( m_Components.Base(), m_Components.Count() ); + } +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::SetComplete( int nComplete ) +{ + m_bComplete.Set( true ); + m_CompleteCount.Set( max( 0, nComplete ) ); + m_Components.Purge(); + m_Weights.Purge(); +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +int CDmeSingleIndexedComponent::GetComplete() const +{ + return IsComplete() ? m_CompleteCount.Get() : 0; +} + + +//----------------------------------------------------------------------------- +// Reset to an empty selection +//----------------------------------------------------------------------------- +inline void CDmeSingleIndexedComponent::Clear() +{ + CDmeComponent::Clear(); + m_CompleteCount.Set( 0 ); + m_Components.RemoveAll(); + m_Weights.RemoveAll(); +} + + +//----------------------------------------------------------------------------- +// Searches for the component in the sorted component list and returns the +// index if it's found or if it's not found, returns the index at which it +// should be inserted to maintain the sorted order of the component list +//----------------------------------------------------------------------------- +int CDmeSingleIndexedComponent::BinarySearch( int component ) const +{ + const CUtlVector< int > &components( m_Components.Get() ); + const int nComponents( components.Count() ); + + int left( 0 ); + int right( nComponents - 1 ); + int mid; + + while ( left <= right ) + { + mid = ( left + right ) >> 1; // floor( ( left + right ) / 2.0 ) + if ( component > m_Components[ mid ] ) + { + left = mid + 1; + } + else if ( component < m_Components[ mid ] ) + { + right = mid - 1; + } + else + { + return mid; + } + } + + return left; +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CDmeSingleIndexedComponent::HasComponent( int component ) const +{ + if ( IsComplete() ) + return true; + + const int cIndex = BinarySearch( component ); + if ( cIndex >= m_Components.Count() ) + return false; + + if ( m_Components[ cIndex ] == component ) + return true; + + return false; +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CDmeSingleIndexedComponent::GetWeight( int component, float &weight ) const +{ + Assert( !IsComplete() ); + + const int cIndex = BinarySearch( component ); + if ( cIndex >= m_Components.Count() ) + return false; + + if ( m_Components[ cIndex ] == component ) + { + weight = m_Weights[ cIndex ]; + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::Subtract( const CDmeSingleIndexedComponent &rhs ) +{ + const int nLhs = Count(); + const int nRhs = rhs.Count(); + + int l = 0; + int r = 0; + + if ( IsComplete() ) + { + // TODO + Assert( 0 ); + } + else + { + CUtlVector< int > newComponents; + newComponents.EnsureCapacity( nLhs ); + CUtlVector< float > newWeights; + newWeights.EnsureCapacity( nLhs ); + + while ( l < nLhs || r < nRhs ) + { + // In LHS but not RHS + while ( l < nLhs && ( r >= nRhs || m_Components[ l ] < rhs.m_Components[ r ] ) ) + { + newComponents.AddToTail( m_Components[ l ] ); + newWeights.AddToTail( m_Weights[ l ] ); + ++l; + } + + // In RHS but not LHS + while ( r < nRhs && ( l >= nLhs || m_Components[ l ] > rhs.m_Components[ r ] ) ) + { + ++r; + } + + // In Both LHS & RHS + while ( l < nLhs && r < nRhs && m_Components[ l ] == rhs.m_Components[ r ] ) + { + ++l; + ++r; + } + } + + m_Components.CopyArray( newComponents.Base(), newComponents.Count() ); + m_Weights.CopyArray( newWeights.Base(), newWeights.Count() ); + } + + m_CompleteCount.Set( 0 ); + m_bComplete.Set( false ); +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::Add( const CDmeSingleIndexedComponent &rhs ) +{ + int nLhs = Count(); + const int nRhs = rhs.Count(); + + int l = 0; + int r = 0; + + if ( IsComplete() ) + { + if ( rhs.IsComplete() && nRhs > nLhs ) + { + m_CompleteCount.Set( nRhs ); + } + else + { + while ( r < nRhs ) + { + if ( rhs.m_Components[ r ] >= nLhs ) + { + // Got one that's greater than the complete count of this one + + CUtlVector< int > newComponents; + newComponents.EnsureCapacity( nLhs + nRhs - r ); + + CUtlVector< float > newWeights; + newWeights.EnsureCapacity( nLhs + nRhs - r ); + + GetComponents( newComponents, newWeights ); + + while ( r < nRhs ) + { + newComponents.AddToTail( rhs.m_Components[ r ] ); + newWeights.AddToTail( rhs.m_Weights[ r ] ); + ++r; + } + + m_Components.CopyArray( newComponents.Base(), newComponents.Count() ); + m_Weights.CopyArray( newWeights.Base(), newWeights.Count() ); + + m_CompleteCount.Set( 0 ); + m_bComplete.Set( false ); + + break; + } + + ++r; + } + } + } + else + { + CUtlVector< int > newComponents; + newComponents.EnsureCapacity( nLhs + nRhs * 0.5 ); // Just an estimate assuming 50% of the components in rhs aren't in lhs + CUtlVector< float > newWeights; + newWeights.EnsureCapacity( nLhs + nRhs * 0.5 ); // Just an estimate + + while ( l < nLhs || r < nRhs ) + { + while ( l < nLhs && ( r >= nRhs || m_Components[ l ] < rhs.m_Components[ r ] ) ) + { + newComponents.AddToTail( m_Components[ l ] ); + newWeights.AddToTail( m_Weights[ l ] ); + ++l; + } + + // In RHS but not LHS + while ( r < nRhs && ( l >= nLhs || m_Components[ l ] > rhs.m_Components[ r ] ) ) + { + newComponents.AddToTail( rhs.m_Components[ r ] ); + newWeights.AddToTail( rhs.m_Weights[ r ] ); + ++r; + } + + // In Both LHS & RHS + while ( l < nLhs && r < nRhs && m_Components[ l ] == rhs.m_Components[ r ] ) + { + newComponents.AddToTail( m_Components[ l ] ); + newWeights.AddToTail( m_Weights[ l ] ); + ++l; + ++r; + } + } + + m_Components.CopyArray( newComponents.Base(), newComponents.Count() ); + m_Weights.CopyArray( newWeights.Base(), newWeights.Count() ); + } + + m_CompleteCount.Set( 0 ); + m_bComplete.Set( false ); +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +void CDmeSingleIndexedComponent::Intersection( const CDmeSingleIndexedComponent &rhs ) +{ + const int nLhs = Count(); + const int nRhs = rhs.Count(); + + int l = 0; + int r = 0; + + if ( IsComplete() ) + { + // TODO + Assert( 0 ); + } + else + { + CUtlVector< int > newComponents; + newComponents.EnsureCapacity( nLhs ); + CUtlVector< float > newWeights; + newWeights.EnsureCapacity( nLhs ); + + while ( l < nLhs || r < nRhs ) + { + // In LHS but not RHS + while ( l < nLhs && ( r >= nRhs || m_Components[ l ] < rhs.m_Components[ r ] ) ) + { + ++l; + } + + // In RHS but not LHS + while ( r < nRhs && ( l >= nLhs || m_Components[ l ] > rhs.m_Components[ r ] ) ) + { + ++r; + } + + // In Both LHS & RHS + while ( l < nLhs && r < nRhs && m_Components[ l ] == rhs.m_Components[ r ] ) + { + newComponents.AddToTail( m_Components[ l ] ); + newWeights.AddToTail( m_Weights[ l ] ); + ++l; + ++r; + } + } + + m_Components.CopyArray( newComponents.Base(), newComponents.Count() ); + m_Weights.CopyArray( newWeights.Base(), newWeights.Count() ); + } + + m_CompleteCount.Set( 0 ); + m_bComplete.Set( false ); +}
\ No newline at end of file |