PDA

View Full Version : geometric hit-testing solution

CarstenT
01-30-2015, 02:45 AM
Hi all,
I'll pop as solution to a question that most of you will ask yourself sooner or later. It's a hit-test alternative to reading an extra depth-buffer. It uses a C++ function object which is new to me and thus may be the reason for my heureka feeling. The code also uses glm. I'll copy paste and let you try to figure out.

class isWithin
/**
This Function-Object can be used in hit-testing for anything from a point to a rectangle ;o)
h in Height and Width means 'half'
rectangle would be
position: center - vec2(hWidth,hHeight)
width = 2*hWidth
height = 2*hHeight
it keeps state in isHit
*/
{ glm::vec2 center ; float hWidth ; float hHeight;
public:
isWithin( glm::vec2 aP , float halfWidth, float halfHeight ) : center(aP.x, aP.y), hWidth(halfWidth) , hHeight(halfHeight) {}
bool operator()( glm::vec2 someP ) { return ( std::abs(someP.x-center.x)<= hWidth)&& (std::abs(someP.y-center.y)<= hHeight) ; m_isHit=true;}
bool isHit(){ return m_isHit; } // keeps state
void reset(){ m_isHit=false; }
virtual~isWithin( ){};
private:
bool m_isHit ;
};

-------------

I test the code in a consol main(){}

auto rando = bind(uniform_int_distribution<>{0,9},default_random_engine{});

glm::vec2 butPos;
butPos = glm::vec2( 1.0*rando() , 1.0*rando() ) ;

isWithin but1 {butPos , 3.0 , 1.0 } ;

glm::vec2 movingPoint;
int counter=0;

for(int y = 0 ; y<10 ; y++)
{
for(int x = 0 ; x<10 ; x++)
{
movingPoint = glm::vec2( 1.0*x , 1.0*y) ;
if(but1(movingPoint) ){ cout << 1 ;}else{ cout << "O" ; }
counter++;
}
if(counter>9){counter=0; cout << endl; }

}

---------------------------------------

I'll try to apply a rotation-matrix on the vectors involved (geometric line centerpoint and incomming cursor-positions to test) - to let the hit-test work on a slim rectangle around an arbitrary line-segment. Conseptually: the line-centerpoint is rotated to the x-axis through P0, and the above hit-tester can be used with a small height and width = line-length. The matrix must rotate an inkomming point, but that should by now be a slim case for you ;o)

There you go - and thanks for helping me out on the problems I had over the years ;o)