bool SceneObject::collideBox(const Point3F &start, const Point3F &end, RayInfo *info)
{
const F32 * pStart = (const F32*)start;
const F32 * pEnd = (const F32*)end;
const F32 * pMin = (const F32*)mObjBox.minExtents;
const F32 * pMax = (const F32*)mObjBox.maxExtents;
F32 maxStartTime = -1;
F32 minEndTime = 1;
F32 startTime;
F32 endTime;
// used for getting normal
U32 hitIndex = 0xFFFFFFFF;
U32 side;
// walk the axis
for(U32 i = 0; i < 3; i++)
{
//
if(pStart[i] < pEnd[i])
{
if(pEnd[i] < pMin[i] || pStart[i] > pMax[i])
return(false);
F32 dist = pEnd[i] - pStart[i];
startTime = (pStart[i] < pMin[i]) ? (pMin[i] - pStart[i]) / dist : -1;
endTime = (pEnd[i] > pMax[i]) ? (pMax[i] - pStart[i]) / dist : 1;
side = 1;
}
else
{
if(pStart[i] < pMin[i] || pEnd[i] > pMax[i])
return(false);
F32 dist = pStart[i] - pEnd[i];
startTime = (pStart[i] > pMax[i]) ? (pStart[i] - pMax[i]) / dist : -1;
endTime = (pEnd[i] < pMin[i]) ? (pStart[i] - pMin[i]) / dist : 1;
side = 0;
}
//
if(startTime > maxStartTime)
{
maxStartTime = startTime;
hitIndex = i * 2 + side;
}
if(endTime < minEndTime)
minEndTime = endTime;
if(minEndTime < maxStartTime)
return(false);
}
// fail if inside
if(maxStartTime < 0.f)
return(false);
//
static Point3F boxNormals[] = {
Point3F( 1, 0, 0),
Point3F(-1, 0, 0),
Point3F( 0, 1, 0),
Point3F( 0,-1, 0),
Point3F( 0, 0, 1),
Point3F( 0, 0,-1),
};
//
AssertFatal(hitIndex != 0xFFFFFFFF, "SceneObject::collideBox");
info->t = maxStartTime;
info->object = this;
mObjToWorld.mulV(boxNormals[hitIndex], &info->normal);
info->material = 0;
return(true);
}