/////////////////////////////////////////////////////////////////////////////// // // Name: HFTracer.cpp // Author: Rich Cross // Contact: rich@wildfiregames.com // /////////////////////////////////////////////////////////////////////////////// #include "precompiled.h" #include "HFTracer.h" #include "Terrain.h" #include "Bound.h" #include "Vector3D.h" extern CTerrain g_Terrain; /////////////////////////////////////////////////////////////////////////////// // CHFTracer constructor CHFTracer::CHFTracer(const u16* hf,u32 mapsize,float cellsize,float heightscale) : m_Heightfield(hf), m_MapSize(mapsize), m_CellSize(cellsize), m_HeightScale(heightscale) { } /////////////////////////////////////////////////////////////////////////////// // RayTriIntersect: intersect a ray with triangle defined by vertices // v0,v1,v2; return true if ray hits triangle at distance less than dist, // or false otherwise bool CHFTracer::RayTriIntersect(const CVector3D& v0,const CVector3D& v1,const CVector3D& v2, const CVector3D& origin,const CVector3D& dir,float& dist) const { const float EPSILON=0.00001f; // calculate edge vectors CVector3D edge0=v1-v0; CVector3D edge1=v2-v0; // begin calculating determinant - also used to calculate U parameter CVector3D pvec=dir.Cross(edge1); // if determinant is near zero, ray lies in plane of triangle float det = edge0.Dot(pvec); if (fabs(det)1.01f) return false; // prepare to test V parameter CVector3D qvec=tvec.Cross(edge0); // calculate V parameter and test bounds float v=dir.Dot(qvec)*inv_det; if (v<0.0f || u+v>1.0f) return false; // calculate distance to intersection point from ray origin float d=edge1.Dot(qvec)*inv_det; if (d>=0 && d0) { traversalPt=origin+dir*tmin; } else { traversalPt=origin; } // setup traversal variables int sx=dir.X<0 ? -1 : 1; int sz=dir.Z<0 ? -1 : 1; float invCellSize=1.0f/float(m_CellSize); float fcx=traversalPt.X*invCellSize; int cx=int(fcx); float fcz=traversalPt.Z*invCellSize; int cz=int(fcz); float invdx=float(1.0/fabs(dir.X)); float invdz=float(1.0/fabs(dir.Z)); float dist; do { // test current cell if (cx>=0 && cx=0 && cz=0); // fell off end of heightmap with no intersection; return a miss return false; }