diff --git a/source/terrain/HFTracer.cpp b/source/terrain/HFTracer.cpp new file mode 100755 index 0000000000..b326a7c852 --- /dev/null +++ b/source/terrain/HFTracer.cpp @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Name: HFTracer.cpp +// Author: Rich Cross +// Contact: rich@wildfiregames.com +// +/////////////////////////////////////////////////////////////////////////////// + +#include "HFTracer.h" +#include "terrain/Terrain.h" +#include "terrain/Bound.h" +#include "terrain/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; +} diff --git a/source/terrain/HFTracer.h b/source/terrain/HFTracer.h new file mode 100755 index 0000000000..97f0a02850 --- /dev/null +++ b/source/terrain/HFTracer.h @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Name: HFTracer.h +// Author: Rich Cross +// Contact: rich@wildfiregames.com +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _HFTRACER_H +#define _HFTRACER_H + +class CVector3D; + +#include "res/res.h" + +/////////////////////////////////////////////////////////////////////////////// +// CHFTracer: a class for determining ray intersections with a heightfield +class CHFTracer +{ +public: + // constructor; setup data + CHFTracer(const u16* hf,u32 mapsize,float cellsize,float heightscale); + + // intersect ray with this heightfield; return true if intersection + // occurs (and fill in grid coordinates and point of intersection), or false otherwise + bool RayIntersect(CVector3D& origin,CVector3D& dir,int& x,int& z,CVector3D& ipt) const; + +private: + // 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 RayTriIntersect(const CVector3D& v0,const CVector3D& v1,const CVector3D& v2, + const CVector3D& origin,const CVector3D& dir,float& dist) const; + + // test if ray intersects either of the triangles in the given + bool CellIntersect(int cx,int cz,CVector3D& origin,CVector3D& dir,float& dist) const; + + // the heightfield were tracing + const u16* m_Heightfield; + // size of the heightfield + u32 m_MapSize; + // cell size - size of each cell in x and z + float m_CellSize; + // vertical scale - size of each cell in y + float m_HeightScale; +}; + +#endif \ No newline at end of file