2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #ifndef __VECTORSET_H__
30 #define __VECTORSET_H__
33 ===============================================================================
37 Creates a set of vectors without duplicates.
39 ===============================================================================
42 template< class type, int dimension >
43 class idVectorSet : public idList<type> {
46 idVectorSet( const type &mins, const type &maxs, const int boxHashSize, const int initialSize );
48 // returns total size of allocated memory
49 size_t Allocated( void ) const { return idList<type>::Allocated() + hash.Allocated(); }
50 // returns total size of allocated memory including size of type
51 size_t Size( void ) const { return sizeof( *this ) + Allocated(); }
53 void Init( const type &mins, const type &maxs, const int boxHashSize, const int initialSize );
54 void ResizeIndex( const int newSize );
57 int FindVector( const type &v, const float epsilon );
64 float boxInvSize[dimension];
65 float boxHalfSize[dimension];
68 template< class type, int dimension >
69 ID_INLINE idVectorSet<type,dimension>::idVectorSet( void ) {
70 hash.Clear( idMath::IPow( boxHashSize, dimension ), 128 );
72 memset( boxInvSize, 0, dimension * sizeof( boxInvSize[0] ) );
73 memset( boxHalfSize, 0, dimension * sizeof( boxHalfSize[0] ) );
76 template< class type, int dimension >
77 ID_INLINE idVectorSet<type,dimension>::idVectorSet( const type &mins, const type &maxs, const int boxHashSize, const int initialSize ) {
78 Init( mins, maxs, boxHashSize, initialSize );
81 template< class type, int dimension >
82 ID_INLINE void idVectorSet<type,dimension>::Init( const type &mins, const type &maxs, const int boxHashSize, const int initialSize ) {
86 idList<type>::AssureSize( initialSize );
87 idList<type>::SetNum( 0, false );
89 hash.Clear( idMath::IPow( boxHashSize, dimension ), initialSize );
93 this->boxHashSize = boxHashSize;
95 for ( i = 0; i < dimension; i++ ) {
96 boxSize = ( maxs[i] - mins[i] ) / (float) boxHashSize;
97 boxInvSize[i] = 1.0f / boxSize;
98 boxHalfSize[i] = boxSize * 0.5f;
102 template< class type, int dimension >
103 ID_INLINE void idVectorSet<type,dimension>::ResizeIndex( const int newSize ) {
104 idList<type>::Resize( newSize );
105 hash.ResizeIndex( newSize );
108 template< class type, int dimension >
109 ID_INLINE void idVectorSet<type,dimension>::Clear( void ) {
110 idList<type>::Clear();
114 template< class type, int dimension >
115 ID_INLINE int idVectorSet<type,dimension>::FindVector( const type &v, const float epsilon ) {
116 int i, j, k, hashKey, partialHashKey[dimension];
118 for ( i = 0; i < dimension; i++ ) {
119 assert( epsilon <= boxHalfSize[i] );
120 partialHashKey[i] = (int) ( ( v[i] - mins[i] - boxHalfSize[i] ) * boxInvSize[i] );
123 for ( i = 0; i < ( 1 << dimension ); i++ ) {
126 for ( j = 0; j < dimension; j++ ) {
127 hashKey *= boxHashSize;
128 hashKey += partialHashKey[j] + ( ( i >> j ) & 1 );
131 for ( j = hash.First( hashKey ); j >= 0; j = hash.Next( j ) ) {
132 const type &lv = (*this)[j];
133 for ( k = 0; k < dimension; k++ ) {
134 if ( idMath::Fabs( lv[k] - v[k] ) > epsilon ) {
138 if ( k >= dimension ) {
145 for ( i = 0; i < dimension; i++ ) {
146 hashKey *= boxHashSize;
147 hashKey += (int) ( ( v[i] - mins[i] ) * boxInvSize[i] );
150 hash.Add( hashKey, idList<type>::Num() );
152 return idList<type>::Num()-1;
157 ===============================================================================
161 Creates a subset without duplicates from an existing list with vectors.
163 ===============================================================================
166 template< class type, int dimension >
167 class idVectorSubset {
169 idVectorSubset( void );
170 idVectorSubset( const type &mins, const type &maxs, const int boxHashSize, const int initialSize );
172 // returns total size of allocated memory
173 size_t Allocated( void ) const { return idList<type>::Allocated() + hash.Allocated(); }
174 // returns total size of allocated memory including size of type
175 size_t Size( void ) const { return sizeof( *this ) + Allocated(); }
177 void Init( const type &mins, const type &maxs, const int boxHashSize, const int initialSize );
180 // returns either vectorNum or an index to a previously found vector
181 int FindVector( const type *vectorList, const int vectorNum, const float epsilon );
188 float boxInvSize[dimension];
189 float boxHalfSize[dimension];
192 template< class type, int dimension >
193 ID_INLINE idVectorSubset<type,dimension>::idVectorSubset( void ) {
194 hash.Clear( idMath::IPow( boxHashSize, dimension ), 128 );
196 memset( boxInvSize, 0, dimension * sizeof( boxInvSize[0] ) );
197 memset( boxHalfSize, 0, dimension * sizeof( boxHalfSize[0] ) );
200 template< class type, int dimension >
201 ID_INLINE idVectorSubset<type,dimension>::idVectorSubset( const type &mins, const type &maxs, const int boxHashSize, const int initialSize ) {
202 Init( mins, maxs, boxHashSize, initialSize );
205 template< class type, int dimension >
206 ID_INLINE void idVectorSubset<type,dimension>::Init( const type &mins, const type &maxs, const int boxHashSize, const int initialSize ) {
210 hash.Clear( idMath::IPow( boxHashSize, dimension ), initialSize );
214 this->boxHashSize = boxHashSize;
216 for ( i = 0; i < dimension; i++ ) {
217 boxSize = ( maxs[i] - mins[i] ) / (float) boxHashSize;
218 boxInvSize[i] = 1.0f / boxSize;
219 boxHalfSize[i] = boxSize * 0.5f;
223 template< class type, int dimension >
224 ID_INLINE void idVectorSubset<type,dimension>::Clear( void ) {
225 idList<type>::Clear();
229 template< class type, int dimension >
230 ID_INLINE int idVectorSubset<type,dimension>::FindVector( const type *vectorList, const int vectorNum, const float epsilon ) {
231 int i, j, k, hashKey, partialHashKey[dimension];
232 const type &v = vectorList[vectorNum];
234 for ( i = 0; i < dimension; i++ ) {
235 assert( epsilon <= boxHalfSize[i] );
236 partialHashKey[i] = (int) ( ( v[i] - mins[i] - boxHalfSize[i] ) * boxInvSize[i] );
239 for ( i = 0; i < ( 1 << dimension ); i++ ) {
242 for ( j = 0; j < dimension; j++ ) {
243 hashKey *= boxHashSize;
244 hashKey += partialHashKey[j] + ( ( i >> j ) & 1 );
247 for ( j = hash.First( hashKey ); j >= 0; j = hash.Next( j ) ) {
248 const type &lv = vectorList[j];
249 for ( k = 0; k < dimension; k++ ) {
250 if ( idMath::Fabs( lv[k] - v[k] ) > epsilon ) {
254 if ( k >= dimension ) {
261 for ( i = 0; i < dimension; i++ ) {
262 hashKey *= boxHashSize;
263 hashKey += (int) ( ( v[i] - mins[i] ) * boxInvSize[i] );
266 hash.Add( hashKey, vectorNum );
270 #endif /* !__VECTORSET_H__ */