etqw-sdk/source/idlib/geometry/Surface_Traceable.h

197 lines
5.1 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#ifndef __SURFACE_TRACEABLE_H__
#define __SURFACE_TRACEABLE_H__
/*
===============================================================================
Traceable surface.
===============================================================================
*/
class idSurface_Traceable : public idSurface {
public:
idSurface_Traceable( void );
idSurface_Traceable( const idSurface &surf ) :
idSurface( surf ),
hash( NULL ),
traceCount( 0 ),
triPlanes( NULL ),
lastTriTrace( NULL ) {
bounds.Clear();
}
~idSurface_Traceable( void );
const idBounds& GetBounds( void );
void SetTraceFraction( const float traceFraction );
void OptimizeForTracing( const float traceFraction = 1.f );
// intersection point is start + dir * scale
bool RayIntersection( /*idList< int >& tracedTris,*/ const idVec3 &start, const idVec3 &dir, float &scale, idDrawVert& dv, bool backFaceCull = false ) const;
protected:
class sdTraceableTriangleHash {
public:
struct hashTriangle_t {
int triIndex;
hashTriangle_t* next;
};
struct hashBin_t {
size_t lastTrace;
hashTriangle_t* triangleList;
};
sdTraceableTriangleHash( idSurface_Traceable& surface, const int binsPerAxis = 50, const int snapFractions = 32 );
~sdTraceableTriangleHash( void );
const idBounds& GetBounds( void ) const { return bounds; }
hashBin_t* GetHashBin( const idVec3& point );
private:
int binsPerAxis;
int snapFractions;
idBounds bounds;
hashBin_t* bins;
idVec3 scale;
int intMins[ 3 ];
int intScale[ 3 ];
idBlockAlloc< hashTriangle_t, 128 > triangleAllocator;
private:
int BinIndex( const int x, const int y, const int z ) const { return ( ( binsPerAxis * binsPerAxis * z ) + ( binsPerAxis * y ) + x ); }
};
idBounds bounds;
sdTraceableTriangleHash* hash;
float traceDist;
mutable size_t traceCount;
idPlane* triPlanes;
size_t* lastTriTrace;
protected:
void GenerateHash( void );
void GenerateIntersectionDrawVert( const idVec3& intersection, const int intersectedTriIndex, idDrawVert& dv ) const;
};
/*
====================
idSurface_Traceable::sdTraceableTriangleHash::~sdTraceableTriangleHash
====================
*/
ID_INLINE idSurface_Traceable::sdTraceableTriangleHash::~sdTraceableTriangleHash( void ) {
delete [] bins;
triangleAllocator.Shutdown();
}
/*
====================
idSurface_Traceable::sdTraceableTriangleHash::GetHashBin
====================
*/
ID_INLINE idSurface_Traceable::sdTraceableTriangleHash::hashBin_t* idSurface_Traceable::sdTraceableTriangleHash::GetHashBin( const idVec3& point ) {
int block[ 3 ];
// snap the point to integral values
for ( int i = 0; i < 3; i++ ) {
block[ i ] = idMath::Ftoi( idMath::Floor( ( point[ i ] + .5f / snapFractions ) * snapFractions ) );
block[ i ] = ( block[ i ] - intMins[ i ] ) / intScale[ i ];
if ( block[ i ] < 0 ) {
block[ i ] = 0;
} else if ( block[ i ] >= binsPerAxis ) {
block[ i ] = binsPerAxis - 1;
}
}
return &bins[ BinIndex( block[ 0 ], block[ 1 ], block[ 2 ] ) ];
}
/*
====================
idSurface_Traceable::idSurface_Traceable
====================
*/
ID_INLINE idSurface_Traceable::idSurface_Traceable( void ) :
hash( NULL ),
traceCount( 0 ),
triPlanes( NULL ),
lastTriTrace( NULL ) {
bounds.Clear();
}
/*
====================
idSurface_Traceable::~idSurface_Traceable
====================
*/
ID_INLINE idSurface_Traceable::~idSurface_Traceable( void ) {
delete hash;
delete [] triPlanes;
delete [] lastTriTrace;
}
/*
====================
idSurface_Traceable::GetBounds
====================
*/
ID_INLINE const idBounds& idSurface_Traceable::GetBounds( void ) {
if ( bounds.IsCleared() ) {
//SIMDProcessor->MinMax( bounds[0], bounds[1], verts.Begin(), indexes.Begin(), indexes.Num() );
}
return bounds;
}
/*
====================
idSurface_Traceable::SetTraceFraction
====================
*/
ID_INLINE void idSurface_Traceable::SetTraceFraction( const float traceFraction ) {
traceDist = 0.f;
// the traceDist will be the traceFrac times the largest bounds axis
for ( int i = 0; i < 3; i++ ) {
float d;
d = traceFraction * ( GetBounds()[1][i] - GetBounds()[0][i] );
if ( d > traceDist ) {
traceDist = d;
}
}
}
/*
====================
idSurface_Traceable::OptimizeForTracing
====================
*/
ID_INLINE void idSurface_Traceable::OptimizeForTracing( const float traceFraction ) {
delete hash;
delete [] triPlanes;
delete [] lastTriTrace;
hash = new sdTraceableTriangleHash( *this );
triPlanes = new idPlane[ indexes.Num() / 3 ];
SIMDProcessor->DeriveTriPlanes( triPlanes, verts.Begin(), verts.Num(), indexes.Begin(), indexes.Num() );
lastTriTrace = new size_t[ indexes.Num() / 3 ];
memset( lastTriTrace, 0, indexes.Num() / 3 * sizeof( size_t ) );
SetTraceFraction( traceFraction );
}
#endif /* !__SURFACE_TRACEABLE_H__ */