113 lines
3.6 KiB
C++
113 lines
3.6 KiB
C++
#include "SSurface.h"
|
|
#include <Common/CRayCollisionTester.h>
|
|
#include <Common/Math.h>
|
|
#include <Core/CDrawUtil.h>
|
|
|
|
std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, float LineThreshold)
|
|
{
|
|
bool Hit = false;
|
|
float HitDist;
|
|
|
|
for (u32 iPrim = 0; iPrim < Primitives.size(); iPrim++)
|
|
{
|
|
SPrimitive *pPrim = &Primitives[iPrim];
|
|
u32 NumVerts = pPrim->Vertices.size();
|
|
|
|
// Triangles
|
|
if ((pPrim->Type == eGX_Triangles) || (pPrim->Type == eGX_TriangleFan) || (pPrim->Type == eGX_TriangleStrip))
|
|
{
|
|
u32 NumTris;
|
|
|
|
if (pPrim->Type == eGX_Triangles)
|
|
NumTris = NumVerts / 3;
|
|
else
|
|
NumTris = NumVerts - 2;
|
|
|
|
for (u32 iTri = 0; iTri < NumTris; iTri++)
|
|
{
|
|
CVector3f vtxA, vtxB, vtxC;
|
|
|
|
// Get the three vertices that make up the current tri
|
|
if (pPrim->Type == eGX_Triangles)
|
|
{
|
|
u32 VertIndex = iTri * 3;
|
|
vtxA = pPrim->Vertices[VertIndex].Position;
|
|
vtxB = pPrim->Vertices[VertIndex+1].Position;
|
|
vtxC = pPrim->Vertices[VertIndex+2].Position;
|
|
}
|
|
|
|
else if (pPrim->Type == eGX_TriangleFan)
|
|
{
|
|
vtxA = pPrim->Vertices[0].Position;
|
|
vtxB = pPrim->Vertices[iTri+1].Position;
|
|
vtxC = pPrim->Vertices[iTri+2].Position;
|
|
}
|
|
|
|
else if (pPrim->Type = eGX_TriangleStrip)
|
|
{
|
|
if (iTri & 0x1)
|
|
{
|
|
vtxA = pPrim->Vertices[iTri+2].Position;
|
|
vtxB = pPrim->Vertices[iTri+1].Position;
|
|
vtxC = pPrim->Vertices[iTri].Position;
|
|
}
|
|
|
|
else
|
|
{
|
|
vtxA = pPrim->Vertices[iTri].Position;
|
|
vtxB = pPrim->Vertices[iTri+1].Position;
|
|
vtxC = pPrim->Vertices[iTri+2].Position;
|
|
}
|
|
}
|
|
|
|
// Intersection test
|
|
std::pair<bool,float> TriResult = Math::RayTriangleIntersection(Ray, vtxA, vtxB, vtxC);
|
|
|
|
if (TriResult.first)
|
|
{
|
|
if ((!Hit) || (TriResult.second < HitDist))
|
|
{
|
|
Hit = true;
|
|
HitDist = TriResult.second;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Lines
|
|
if ((pPrim->Type == eGX_Lines) || (pPrim->Type == eGX_LineStrip))
|
|
{
|
|
u32 NumLines;
|
|
|
|
if (pPrim->Type == eGX_Lines)
|
|
NumLines = NumVerts / 2;
|
|
else
|
|
NumLines = NumVerts - 1;
|
|
|
|
for (u32 iLine = 0; iLine < NumLines; iLine++)
|
|
{
|
|
CVector3f vtxA, vtxB;
|
|
|
|
// Get the two vertices that make up the current line
|
|
u32 index = (pPrim->Type == eGX_Lines ? iLine * 2 : iLine);
|
|
vtxA = pPrim->Vertices[index].Position;
|
|
vtxB = pPrim->Vertices[index+1].Position;
|
|
|
|
// Intersection test
|
|
std::pair<bool,float> result = Math::RayLineIntersection(Ray, vtxA, vtxB, LineThreshold);
|
|
|
|
if (result.first)
|
|
{
|
|
if ((!Hit) || (result.second < HitDist))
|
|
{
|
|
Hit = true;
|
|
HitDist = result.second;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return std::pair<bool,float>(Hit, HitDist);
|
|
}
|