123
This commit is contained in:
156
Editor/Util/BBox.cpp
Normal file
156
Editor/Util/BBox.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Crytek Engine Source File.
|
||||
// Copyright (C), Crytek Studios, 2002.
|
||||
// -------------------------------------------------------------------------
|
||||
// File name: bbox.cpp
|
||||
// Version: v1.00
|
||||
// Created: 2/7/2002 by Timur.
|
||||
// Compilers: Visual Studio.NET
|
||||
// Description:
|
||||
// -------------------------------------------------------------------------
|
||||
// History:
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "BBox.h"
|
||||
|
||||
typedef unsigned int udword;
|
||||
|
||||
// Integer representation of a floating-Vec3 value.
|
||||
#define IR(x) ((udword&)x)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* A method to compute a ray-AABB intersection.
|
||||
* Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990
|
||||
* Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
|
||||
* Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only)
|
||||
*
|
||||
* Hence this version is faster as well as more robust than the original one.
|
||||
*
|
||||
* Should work provided:
|
||||
* 1) the integer representation of 0.0f is 0x00000000
|
||||
* 2) the sign bit of the float is the most significant one
|
||||
*
|
||||
* Report bugs: p.terdiman@codercorner.com
|
||||
*
|
||||
* \param aabb [in] the axis-aligned bounding box
|
||||
* \param origin [in] ray origin
|
||||
* \param dir [in] ray direction
|
||||
* \param coord [out] impact coordinates
|
||||
* \return true if ray intersects AABB
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define RAYAABB_EPSILON 0.00001f
|
||||
bool BBox::IsIntersectRay( const Vec3& vOrigin, const Vec3& vDir, Vec3& pntContact )
|
||||
{
|
||||
BOOL Inside = TRUE;
|
||||
float MinB[3] = { min.x,min.y,min.z };
|
||||
float MaxB[3] = { max.x,max.y,max.z };
|
||||
float MaxT[3];
|
||||
MaxT[0]=MaxT[1]=MaxT[2]=-1.0f;
|
||||
float coord[3] = { 0,0,0 };
|
||||
|
||||
float origin[3] = { vOrigin.x,vOrigin.y,vOrigin.z };
|
||||
float dir[3] = { vDir.x,vDir.y,vDir.z };
|
||||
|
||||
// Find candidate planes.
|
||||
for(udword i=0;i<3;i++)
|
||||
{
|
||||
if(origin[i] < MinB[i])
|
||||
{
|
||||
coord[i] = MinB[i];
|
||||
Inside = FALSE;
|
||||
|
||||
// Calculate T distances to candidate planes
|
||||
if(IR(dir[i])) MaxT[i] = (MinB[i] - origin[i]) / dir[i];
|
||||
}
|
||||
else if(origin[i] > MaxB[i])
|
||||
{
|
||||
coord[i] = MaxB[i];
|
||||
Inside = FALSE;
|
||||
|
||||
// Calculate T distances to candidate planes
|
||||
if(IR(dir[i])) MaxT[i] = (MaxB[i] - origin[i]) / dir[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Ray origin inside bounding box
|
||||
if(Inside)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Timur: for editor this need to be treated as intersection.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
pntContact(origin[0],origin[1],origin[2]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get largest of the maxT's for final choice of intersection
|
||||
udword WhichPlane = 0;
|
||||
if(MaxT[1] > MaxT[WhichPlane]) WhichPlane = 1;
|
||||
if(MaxT[2] > MaxT[WhichPlane]) WhichPlane = 2;
|
||||
|
||||
// Check final candidate actually inside box
|
||||
if(IR(MaxT[WhichPlane])&0x80000000) return false;
|
||||
|
||||
for(i=0;i<3;i++)
|
||||
{
|
||||
if(i!=WhichPlane)
|
||||
{
|
||||
coord[i] = origin[i] + MaxT[WhichPlane] * dir[i];
|
||||
#ifdef RAYAABB_EPSILON
|
||||
if(coord[i] < MinB[i] - RAYAABB_EPSILON || coord[i] > MaxB[i] + RAYAABB_EPSILON) return false;
|
||||
#else
|
||||
if(coord[i] < MinB[i] || coord[i] > MaxB[i]) return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
pntContact(coord[0],coord[1],coord[2]);
|
||||
return true; // ray hits box
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BBox::RayEdgeIntersection( const Vec3 &raySrc,const Vec3 &rayDir,float epsilonDist,float &dist,Vec3 &intPnt )
|
||||
{
|
||||
// Check 6 group lines.
|
||||
Vec3 rayTrg = raySrc + rayDir*10000.0f;
|
||||
Vec3 pnt[12];
|
||||
|
||||
float d[12];
|
||||
|
||||
// Near
|
||||
d[0] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,max.z),Vec3(max.x,min.y,max.z),pnt[0] );
|
||||
d[1] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,max.y,max.z),Vec3(max.x,max.y,max.z),pnt[1] );
|
||||
d[2] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,max.z),Vec3(min.x,max.y,max.z),pnt[2] );
|
||||
d[3] = RayToLineDistance( raySrc,rayTrg,Vec3(max.x,min.y,max.z),Vec3(max.x,max.y,max.z),pnt[3] );
|
||||
|
||||
// Far
|
||||
d[4] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,min.z),Vec3(max.x,min.y,min.z),pnt[4] );
|
||||
d[5] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,max.y,min.z),Vec3(max.x,max.y,min.z),pnt[5] );
|
||||
d[6] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,min.z),Vec3(min.x,max.y,min.z),pnt[6] );
|
||||
d[7] = RayToLineDistance( raySrc,rayTrg,Vec3(max.x,min.y,min.z),Vec3(max.x,max.y,min.z),pnt[7] );
|
||||
|
||||
// Sides.
|
||||
d[8] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,min.y,min.z),Vec3(min.x,min.y,max.z),pnt[8] );
|
||||
d[9] = RayToLineDistance( raySrc,rayTrg,Vec3(max.x,min.y,min.z),Vec3(max.x,min.y,max.z),pnt[9] );
|
||||
d[10] = RayToLineDistance( raySrc,rayTrg,Vec3(min.x,max.y,min.z),Vec3(min.x,max.y,max.z),pnt[10] );
|
||||
d[11] = RayToLineDistance( raySrc,rayTrg,Vec3(max.x,max.y,min.z),Vec3(max.x,max.y,max.z),pnt[11] );
|
||||
|
||||
dist = FLT_MAX;
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
if (d[i] < dist)
|
||||
{
|
||||
dist = d[i];
|
||||
intPnt = pnt[i];
|
||||
}
|
||||
}
|
||||
if (dist < epsilonDist)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user