client/EterLib/GrpCollisionObject.cpp

240 lines
6.4 KiB
C++

#include "StdAfx.h"
#include "GrpCollisionObject.h"
bool CGraphicCollisionObject::IntersectBoundBox(const D3DXMATRIX* c_pmatWorld, const TBoundBox& c_rboundBox, float* pu, float* pv, float* pt)
{
return IntersectCube(c_pmatWorld, c_rboundBox.sx, c_rboundBox.sy, c_rboundBox.sz, c_rboundBox.ex, c_rboundBox.ey, c_rboundBox.ez, ms_vtPickRayOrig, ms_vtPickRayDir, pu, pv, pt);
}
bool CGraphicCollisionObject::IntersectCube(const D3DXMATRIX* c_pmatWorld, float sx, float sy, float sz, float ex, float ey, float ez,
D3DXVECTOR3 & RayOriginal, D3DXVECTOR3 & RayDirection, float* pu, float* pv, float* pt)
{
TPosition posVertices[8];
posVertices[0] = TPosition(sx, sy, sz);
posVertices[1] = TPosition(ex, sy, sz);
posVertices[2] = TPosition(sx, ey, sz);
posVertices[3] = TPosition(ex, ey, sz);
posVertices[4] = TPosition(sx, sy, ez);
posVertices[5] = TPosition(ex, sy, ez);
posVertices[6] = TPosition(sx, ey, ez);
posVertices[7] = TPosition(ex, ey, ez);
static const WORD c_awFillCubeIndices[36] = {
0, 1, 2, 1, 3, 2,
2, 0, 6, 0, 4, 6,
0, 1, 4, 1, 5, 4,
1, 3, 5, 3, 7, 5,
3, 2, 7, 2, 6, 7,
4, 5, 6, 5, 7, 6,
};
return IntersectIndexedMesh(
c_pmatWorld,
posVertices,
sizeof(TPosition),
8,
c_awFillCubeIndices,
36,
RayOriginal,
RayDirection,
pu,
pv,
pt
);
}
const int c_iLimitVertexCount = 1024;
bool CGraphicCollisionObject::IntersectIndexedMesh(const D3DXMATRIX* c_pmatWorld, const void* vertices, int step, int vtxCount, const void* indices, int idxCount,
D3DXVECTOR3 & RayOriginal, D3DXVECTOR3 & RayDirection, float* pu, float* pv, float* pt)
{
static D3DXVECTOR3 s_v3PositionArray[c_iLimitVertexCount];
static DWORD s_dwPositionCount;
if (vtxCount > c_iLimitVertexCount)
{
Tracef("The vertex count of mesh which is worked collision detection is too much : %d / %d", vtxCount, c_iLimitVertexCount);
return false;
}
s_dwPositionCount = 0;
char* pcurVtx = (char*)vertices;
while (vtxCount--)
{
float* pos = (float*)pcurVtx;
D3DXVec3TransformCoord(&s_v3PositionArray[s_dwPositionCount++], (D3DXVECTOR3*)pos, c_pmatWorld);
pcurVtx += step;
}
WORD* pcurIdx = (WORD*)indices;
int triCount = idxCount / 3;
while (triCount--)
{
if (IntersectTriangle(RayOriginal, RayDirection,
s_v3PositionArray[pcurIdx[0]],
s_v3PositionArray[pcurIdx[1]],
s_v3PositionArray[pcurIdx[2]],
pu, pv, pt))
{
return true;
}
pcurIdx += 3;
}
return false;
}
bool CGraphicCollisionObject::IntersectMesh(const D3DXMATRIX * c_pmatWorld, const void * vertices, DWORD dwStep, DWORD dwvtxCount, D3DXVECTOR3 & RayOriginal, D3DXVECTOR3 & RayDirection, float* pu, float* pv, float* pt)
{
char * pcurVtx = (char *) vertices;
D3DXVECTOR3 v3Vertex[3];
for (DWORD i = 0; i < dwvtxCount; i += 3)
{
D3DXVec3TransformCoord(&v3Vertex[0], (D3DXVECTOR3*)pcurVtx, c_pmatWorld);
pcurVtx += dwStep;
D3DXVec3TransformCoord(&v3Vertex[1], (D3DXVECTOR3*)pcurVtx, c_pmatWorld);
pcurVtx += dwStep;
D3DXVec3TransformCoord(&v3Vertex[2], (D3DXVECTOR3*)pcurVtx, c_pmatWorld);
pcurVtx += dwStep;
if (IntersectTriangle(RayOriginal, RayDirection,
v3Vertex[0], v3Vertex[1], v3Vertex[2],
pu, pv, pt))
{
return true;
}
}
return false;
}
bool CGraphicCollisionObject::IntersectTriangle(const D3DXVECTOR3& c_orig,
const D3DXVECTOR3& c_dir,
const D3DXVECTOR3& c_v0,
const D3DXVECTOR3& c_v1,
const D3DXVECTOR3& c_v2,
float * pu,
float * pv,
float * pt)
{
D3DXVECTOR3 edge1 = c_v1 - c_v0;
D3DXVECTOR3 edge2 = c_v2 - c_v0;
D3DXVECTOR3 pvec;
D3DXVec3Cross(&pvec, &c_dir, &edge2);
FLOAT det = D3DXVec3Dot(&edge1, &pvec);
D3DXVECTOR3 tvec;
if (det > 0)
{
tvec = c_orig - c_v0;
}
else
{
tvec = c_v0 - c_orig;
det = -det;
}
if (det < 0.0001f)
return false;
float u, v, t;
u = D3DXVec3Dot(&tvec, &pvec);
if (u < 0.0f || u > det)
return false;
D3DXVECTOR3 qvec;
D3DXVec3Cross(&qvec, &tvec, &edge1);
v = D3DXVec3Dot(&c_dir, &qvec);
if (v < 0.0f || u + v > det)
return false;
t = D3DXVec3Dot(&edge2, &qvec);
FLOAT fInvDet = 1.0f / det;
t *= fInvDet;
u *= fInvDet;
v *= fInvDet;
D3DXVECTOR3 spot = edge1 * u + edge2 * v;
spot += c_v0;
*pu = spot.x;
*pv = spot.y;
*pt = t;
return true;
}
bool CGraphicCollisionObject::IntersectSphere(const D3DXVECTOR3 & c_rv3Position, float fRadius, const D3DXVECTOR3 & c_rv3RayOriginal, const D3DXVECTOR3 & c_rv3RayDirection)
{
D3DXVECTOR3 v3RayOriginal = c_rv3RayOriginal - c_rv3Position;
float a = D3DXVec3Dot(&c_rv3RayDirection, &c_rv3RayDirection);
float b = 2 * D3DXVec3Dot(&v3RayOriginal, &c_rv3RayDirection);
float c = D3DXVec3Dot(&v3RayOriginal, &v3RayOriginal) - fRadius * fRadius;
float D = b * b - 4 * a * c;
if (D >= 0)
return true;
return false;
}
bool CGraphicCollisionObject::IntersectCylinder(const D3DXVECTOR3 & c_rv3Position, float fRadius, float fHeight, const D3DXVECTOR3 & c_rv3RayOriginal, const D3DXVECTOR3 & c_rv3RayDirection)
{
D3DXVECTOR3 v3RayOriginal = c_rv3RayOriginal - c_rv3Position;
float a = c_rv3RayDirection.x * c_rv3RayDirection.x + c_rv3RayDirection.y * c_rv3RayDirection.y;
float b = 2 * (v3RayOriginal.x * c_rv3RayDirection.x + v3RayOriginal.y * c_rv3RayDirection.y);
float c = v3RayOriginal.x * v3RayOriginal.x + v3RayOriginal.y * v3RayOriginal.y - fRadius*fRadius;
float D = b * b - 4 * a * c;
if (D > 0)
if (0.0f != a)
{
float tPlus = (-b + sqrtf(D)) / (2 * a);
float tMinus = (-b - sqrtf(D)) / (2 * a);
float fzPlus = v3RayOriginal.z + tPlus * c_rv3RayDirection.z;
float fzMinus = v3RayOriginal.z + tMinus * c_rv3RayDirection.z;
if (fzPlus > 0.0f && fzPlus <= fHeight)
return true;
if (fzMinus > 0.0f && fzMinus <= fHeight)
return true;
if (fzMinus * fzPlus < 0.0f)
return true;
}
return false;
}
bool CGraphicCollisionObject::IntersectSphere(const D3DXVECTOR3 & c_rv3Position, float fRadius)
{
return CGraphicCollisionObject::IntersectSphere(c_rv3Position, fRadius, ms_vtPickRayOrig, ms_vtPickRayDir);
}
bool CGraphicCollisionObject::IntersectCylinder(const D3DXVECTOR3 & c_rv3Position, float fRadius, float fHeight)
{
return CGraphicCollisionObject::IntersectCylinder(c_rv3Position, fRadius, fHeight, ms_vtPickRayOrig, ms_vtPickRayDir);
}
CGraphicCollisionObject::CGraphicCollisionObject()
{
}
CGraphicCollisionObject::~CGraphicCollisionObject()
{
}