"L. Spiro Engine"
|
00001 00016 #ifndef __LSP_POLYGON3BASE_H__ 00017 #define __LSP_POLYGON3BASE_H__ 00018 00019 #include "../LSPPhysicsLib.h" 00020 #include "Allocators/LSAStackAllocator.h" 00021 00022 #include <cassert> 00023 00024 namespace lsp { 00025 00032 template <typename _tType, typename _tSeg3Type, typename _tPlane3Type> 00033 class CPolygon3Base { 00034 public : 00035 // == Various constructors. 00036 LSE_CALLCTOR CPolygon3Base() : 00037 m_ptSegs( NULL ), 00038 m_psaAllocator( NULL ), 00039 m_uiptrUser( 0UL ), 00040 m_ui32Total( 0UL ), 00041 m_bSplitter( false ) { 00042 } 00043 LSE_CALLCTOR ~CPolygon3Base() { 00044 Reset(); 00045 } 00046 00047 00048 // == Operators. 00055 _tSeg3Type * LSE_CALL operator [] ( LSUINT32 _ui32Index ) { 00056 return &Segments()[_ui32Index]; 00057 } 00058 00065 const _tSeg3Type * LSE_CALL operator [] ( LSUINT32 _ui32Index ) const { 00066 return &Segments()[_ui32Index]; 00067 } 00068 00075 CPolygon3Base<_tType, _tSeg3Type, _tPlane3Type> & LSE_CALL 00076 operator = ( const CPolygon3Base<_tType, _tSeg3Type, _tPlane3Type> &_pSrc ) { 00077 Reset(); 00078 Copy( _pSrc, _pSrc.m_psaAllocator ); 00079 return (*this); 00080 } 00081 00082 00083 // == Functions. 00087 LSVOID LSE_CALL Reset() { 00088 for ( ; m_ui32Total--; ) { 00089 m_ptSegs[m_ui32Total].~_tSeg3Type(); // Destroy, don't delete. 00090 } 00091 m_ptSegs = NULL; 00092 m_ui32Total = 0UL; 00093 m_psaAllocator = NULL; 00094 m_uiptrUser = 0UL; 00095 m_bSplitter = false; 00096 } 00097 00105 LSBOOL LSE_CALL Copy( const CPolygon3Base<_tType, _tSeg3Type, _tPlane3Type> &_p3bSrc, CStackAllocator * _psaAllocator ) { 00106 Reset(); 00107 if ( !SetTotalSides( _p3bSrc.TotalSegments(), _psaAllocator ) ) { return false; } 00108 for ( LSUINT32 I = _p3bSrc.TotalSegments(); I--; ) { 00109 m_ptSegs[I] = _p3bSrc.Segments()[I]; 00110 } 00111 m_pPlane = _p3bSrc.m_pPlane; 00112 m_uiptrUser = _p3bSrc.m_uiptrUser; 00113 m_bSplitter = _p3bSrc.m_bSplitter; 00114 return true; 00115 } 00116 00124 LSBOOL LSE_CALL SetTotalSides( LSUINT32 _ui32Total, CStackAllocator * _psaAllocator ) { 00125 Reset(); 00126 m_psaAllocator = _psaAllocator; 00127 if ( _ui32Total < 3UL ) { return false; } 00128 if ( (m_ptSegs = static_cast<_tSeg3Type *>(_psaAllocator->Alloc( sizeof( _tSeg3Type ) * _ui32Total, 4UL ))) ) { 00129 m_ui32Total = _ui32Total; 00130 for ( ; _ui32Total--; ) { 00131 new( &m_ptSegs[_ui32Total] ) _tSeg3Type(); 00132 } 00133 return true; 00134 } 00135 return false; 00136 } 00137 00143 LSUINT32 LSE_CALL TotalSegments() const { 00144 return m_ui32Total; 00145 } 00146 00152 _tSeg3Type * LSE_CALL Segments() { 00153 return m_ptSegs; 00154 } 00155 00161 const _tSeg3Type * LSE_CALL Segments() const { 00162 return m_ptSegs; 00163 } 00164 00170 const _tPlane3Type & LSE_CALL Plane() const { 00171 return m_pPlane; 00172 } 00173 00179 _tPlane3Type & LSE_CALL Plane() { 00180 return m_pPlane; 00181 } 00182 00188 LSVOID LSE_CALL SetUser( LSUINTPTR _uiptrValue ) { 00189 m_uiptrUser = _uiptrValue; 00190 } 00191 00197 LSUINTPTR LSE_CALL GetUser() const { 00198 return m_uiptrUser; 00199 } 00200 00208 LSBOOL LSE_CALL Finalize( _tType _tEpsilon ) { 00209 assert( m_ui32Total >= 3UL ); 00210 _tSeg3Type tTemp; 00211 // Remove any segments that have any missing connections. 00212 for ( LSUINT32 I = 0UL; I < m_ui32Total; ) { 00213 // Check P against Q. 00214 LSBOOL bHasP = false, bHasQ = false; 00215 _tType tLen = (m_ptSegs[I].q - m_ptSegs[I].p).LenSq(); 00216 if ( tLen >= _tEpsilon * _tEpsilon ) { 00217 for ( LSUINT32 J = 0UL; J < m_ui32Total; ++J ) { 00218 if ( J == I ) { continue; } 00219 _tType tDist = (m_ptSegs[I].p - m_ptSegs[J].q).Len(); 00220 if ( tDist <= _tEpsilon ) { 00221 bHasP = true; 00222 break; 00223 } 00224 } 00225 if ( bHasP ) { 00226 // Check its Q. 00227 for ( LSUINT32 J = 0UL; J < m_ui32Total; ++J ) { 00228 if ( J == I ) { continue; } 00229 _tType tDist = (m_ptSegs[I].q - m_ptSegs[J].p).Len(); 00230 if ( tDist <= _tEpsilon ) { 00231 bHasQ = true; 00232 break; 00233 } 00234 } 00235 } 00236 } 00237 00238 if ( !bHasP || !bHasQ ) { 00239 Remove( I ); 00240 if ( m_ui32Total <= 2UL ) { 00241 return false; 00242 } 00243 } 00244 else { 00245 ++I; 00246 } 00247 } 00248 for ( LSUINT32 I = 0UL; I < m_ui32Total; ++I ) { 00249 // Find the starting point that connects to the end point of the Ith edge. 00250 for ( LSUINT32 J = I + 1UL; J < m_ui32Total; ++J ) { 00251 _tType tDist = (m_ptSegs[J].p - m_ptSegs[I].q).Len(); 00252 if ( tDist <= _tEpsilon ) { 00253 if ( J != I + 1UL ) { // No need to swap here. 00254 tTemp = m_ptSegs[I+1]; 00255 m_ptSegs[I+1] = m_ptSegs[J]; 00256 m_ptSegs[J] = tTemp; 00257 } 00258 break; 00259 } 00260 } 00261 } 00262 00263 // Return true if we came full circle. 00264 return (m_ptSegs[0].p - m_ptSegs[m_ui32Total-1].q).Len() <= _tEpsilon; 00265 } 00266 00272 LSVOID LSE_CALL Remove( LSUINT32 _ui32Index ) { 00273 if ( _ui32Index < m_ui32Total ) { 00274 m_ptSegs[_ui32Index].~_tSeg3Type(); // Destroy, don't delete. 00275 for ( LSUINT32 J = _ui32Index + 1UL; J < m_ui32Total; ++J ) { 00276 m_ptSegs[J-1] = m_ptSegs[J]; 00277 } 00278 --m_ui32Total; 00279 } 00280 } 00281 00287 LSBOOL LSE_CALL IsSplitter() const { 00288 return m_bSplitter; 00289 } 00290 00296 LSVOID LSE_CALL SetAsSplitter( LSBOOL _bVal ) { 00297 m_bSplitter = _bVal; 00298 } 00299 00300 00301 protected : 00302 // == Members. 00306 _tSeg3Type * m_ptSegs; 00307 00311 CStackAllocator * m_psaAllocator; 00312 00316 LSUINTPTR m_uiptrUser; 00317 00321 LSUINT32 m_ui32Total; 00322 00326 _tPlane3Type m_pPlane; 00327 00331 LSBOOL m_bSplitter; 00332 00333 }; 00334 00335 } // namespace lsp 00336 00337 #endif // __LSP_POLYGON3BASE_H__