This uses DirectX (d3dx9.h)
Code: Select all
#ifndef EPSILON
#define EPSILON (float)1.0e-6
#endif
struct _PickRayPtData
{
D3DXVECTOR3 vNormal;
D3DXVECTOR3 vIntersectPt;
FLOAT fDistanceSq;
};
struct _PickRayDesc
{
D3DXVECTOR3 vOrigin;
D3DXVECTOR3 vDirection;
_PickRayPtData Pts[2];
// object ray intersected
class TObject* Object = NULL;
BOOL bHit;
};
typedef _PickRayDesc PickRay_Desc, *LPPickRay_Desc;
//==========================================================
struct _AABB
{
float fWidth;
float fHeight;
float fDepth;
D3DXVECTOR3 vMin;
D3DXVECTOR3 vMax;
D3DXVECTOR3 vCenter;
bool PointInBox(D3DXVECTOR3 Pt)
{
return Pt.x > vMin.x && Pt.y > vMin.y && Pt.z > vMin.z &&
Pt.x < vMax.x && Pt.y < vMax.y && Pt.z < vMax.z;
}
static _AABB Make( D3DXVECTOR3 center, float width,float height,float depth)
{
_AABB AB;
AB.fWidth = width;
AB.fHeight = height;
AB.fDepth = depth;
AB.vMin.x = center.x - width ;
AB.vMin.y = center.y - height ;
AB.vMin.z = center.z - depth ;
AB.vMax.x = center.x + width ;
AB.vMax.y = center.y + height ;
AB.vMax.z = center.z + depth ;
AB.vCenter = center;
return AB;
}
bool Overlaps(const _AABB& tBox2)
{
//Check if Box1's max is greater than Box2's min and Box1's min is less than Box2's max
return(vMax.x > tBox2.vMin.x &&
vMin.x < tBox2.vMax.x &&
vMax.y > tBox2.vMin.y &&
vMin.y < tBox2.vMax.y &&
vMax.z > tBox2.vMin.z &&
vMin.z < tBox2.vMax.z);
//If not, it will return false
}
};
typedef _AABB D3_AABB, *LPD3_AABB;
//=========================================================
struct _Sphere
{
D3DXVECTOR3 vCenter;
float fRadius;
static _Sphere Make(D3DXVECTOR3 center, float radius)
{
_Sphere s;
s.vCenter = center;
s.fRadius = radius;
return s;
}
/////////////
//check if a point is in sphere
////////////
bool PointIn(D3DXVECTOR3 pt)
{
D3DXVECTOR3 vecDist(vCenter - pt);
float fDistSq(D3DXVec3Dot(&vecDist, &vecDist));
//Calculate if the squared distance between the sphere's center and the point
//is less than the squared radius of the sphere
if (fDistSq < (fRadius * fRadius))
{
return true;
}
//If not, return false
return false;
}
//////////
// check if ray intersects sphere (no data returned)
// use for quick check
/////////
bool RayIntersectSphere(_PickRayDesc desc)
{
//First, let's see if the point is inside the sphere. If so, return true
if (PointIn(desc.vOrigin))
return true;
//Create a vector from the ray's start to the sphere's center
D3DXVECTOR3 vecV1(vCenter - desc.vOrigin);
//Project this vector onto the ray's direction vector
float fD = D3DXVec3Dot(&vecV1, &desc.vDirection);
//If the ray is pointing away
if (fD < 0.0f)
return false;
//Calculate the closest point to the sphere
D3DXVECTOR3 vecClosestPoint(desc.vOrigin + (desc.vDirection * fD));
//Check if that point is inside the sphere
return (PointIn(vecClosestPoint));
}
/////////////
//Get entry and exit points of sphere
//via pick ray and filling PickRay_Desc data
//caluclates normals of intersect points
////////////
void GetRayIntersectSphereData(_PickRayDesc& desc)
{
D3DXVECTOR3 vantage = desc.vOrigin;
D3DXVECTOR3 direction = desc.vDirection;
// Calculate the coefficients of the quadratic equation
// au^2 + bu + c = 0.
// Solving this equation gives us the value of u
// for any intersection points.
const D3DXVECTOR3 displacement = vantage - vCenter;
const double a = D3DXVec3LengthSq(&direction);
const double b = 2.0 * D3DXVec3Dot(&direction, &displacement);
const double c = D3DXVec3LengthSq(&displacement) - fRadius*fRadius;
// Calculate the radicand of the quadratic equation solution formula.
// The radicand must be non-negative for there to be real solutions.
const double radicand = b*b - 4.0*a*c;
if (radicand >= 0.0)
{
// There are two intersection solutions, one involving
// +sqrt(radicand), the other -sqrt(radicand).
// through and through intersect
desc.bHit = true;
const double root = sqrt(radicand);
const double denom = 2.0 * a;
const double u[2] = {
(-b + root) / denom,
(-b - root) / denom
};
for (int i = 0; i < 2; ++i)
{
if (u[i] > EPSILON)
{
const D3DXVECTOR3 vantageToSurface = u[i] * direction;
desc.Pts[i].vIntersectPt = vantage + vantageToSurface;
// The normal vector to the surface of
// a sphere is outward from the center.
D3DXVec3Normalize(&desc.Pts[i].vNormal, &(desc.Pts[i].vIntersectPt - vCenter));
desc.Pts[i].fDistanceSq = D3DXVec3LengthSq(&vantageToSurface);
}
}
}
else
{
desc.bHit = false;
}
}
};
typedef _Sphere D3_SPHERE, *LPD3_SPHERE;
//==========================================================
struct _Plane
{
D3DXVECTOR3 pt0;
D3DXVECTOR3 pt1;
D3DXVECTOR3 pt2;
D3DXVECTOR3 normal;
static _Plane Make(D3DXVECTOR3 pt0, D3DXVECTOR3 pt1, D3DXVECTOR3 pt2)
{
_Plane p;
p.pt0 = pt0;
p.pt1 = pt1;
p.pt2 = pt2;
p.MakeNormal();
return p;
}
D3DXVECTOR3 MakeNormal()
{
D3DXVECTOR3 Vector1 = { pt1 - pt0 };
D3DXVECTOR3 Vector2 = { pt2 - pt0 };
D3DXVec3Cross(&normal,&Vector1, &Vector2);
D3DXVec3Normalize(&normal, &normal);
return normal;
}
D3DXVECTOR3 Rebound(D3DXVECTOR3 impactVel)
{
return impactVel - 2 * D3DXVec3Dot(&impactVel, &normal) * normal;
}
};