You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
577 lines
15 KiB
577 lines
15 KiB
//========= 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 ); |
|
} |