예제 #1
0
// intersect a ray with the mesh
bool TXGrid3D::IntersectRay(const CVector3f& start, const CVector3f& end) 
{
	// pick rays
	m_rays.push_back(TXRay(start, end));
	CVector3f dir;
	dir.Sub(start,end);

	int idir[3] = {
	fabs(dir.GetX()) < DBL_EPSILON ? 0 : (dir.GetX() > 0 ? 1 : -1),
	fabs(dir.GetY()) < DBL_EPSILON ? 0 : (dir.GetY() > 0 ? 1 : -1),
	fabs(dir.GetZ()) < DBL_EPSILON ? 0 : (dir.GetZ() > 0 ? 1 : -1) };

	double dist = 0;
	CVector3f pos;
	pos.Sub(end, m_min);

	int ix = (int)floor((end.GetX() - m_min.GetX())/m_xstep),
	iy = (int)floor((end.GetY() - m_min.GetY())/m_ystep),
	iz = (int)floor((end.GetZ() - m_min.GetZ())/m_zstep);
	double tx = 1.0, ty = 1.0, tz = 1.0;

	// first cell
	ix = MIN(MAX(ix, 0), m_size-1);
	iy = MIN(MAX(iy, 0), m_size-1);
	iz = MIN(MAX(iz, 0), m_size-1);

	// intersection test, from end to start
	while ((dist < 1) && (ix >= 0) && (ix < m_size) &&(iy >= 0) && (iy < m_size) && (iz >= 0) && (iz < m_size)) 
	{
		int csz = m_grid[ix][iy][iz].size();
		for (int i=0; i<csz; i++) 
		{
			TXGridTriangle* gt = m_grid[ix][iy][iz][i];
			double rpdot = dir.Dot(gt->m_n);
			if (rpdot != 0) 
			{
				CVector3f tmp;
				tmp.Sub(gt->m_t->m_v[0]->m_pos,end);
				double t = tmp.Dot(gt->m_n) / rpdot;

				if (t > DBL_EPSILON && t < 1) 
				{
					CVector3f pt;
					pt.ScaleAdd(t,dir,end);

					CVector3f pt0,pt1,pt2;
					pt0.Sub(pt,gt->m_t->m_v[0]->m_pos);
					pt1.Sub(pt,gt->m_t->m_v[1]->m_pos);
					pt2.Sub(pt,gt->m_t->m_v[2]->m_pos);


					if (pt0.Dot(gt->m_en1)> -DBL_EPSILON &&
					  pt1.Dot(gt->m_en2)>-DBL_EPSILON &&
					  pt2.Dot(gt->m_en3)>-DBL_EPSILON) 
					{
						m_rays[m_rays.size()-1].m_p = t;
						return true;
					}
				}
			}
		}

		// next cell
		if (idir[0] != 0)
		  tx = (m_min.GetX() + (ix+(idir[0]+1)/2)*m_xstep - end.GetX()) / dir.GetX();
		if (idir[1] != 0)
		  ty = (m_min.GetY() + (iy+(idir[1]+1)/2)*m_ystep - end.GetY()) / dir.GetY();
		if (idir[2] != 0)
		  tz = (m_min.GetZ() + (iz+(idir[2]+1)/2)*m_zstep - end.GetZ()) / dir.GetZ();
		if ((tx <= ty) && (tx <= tz)) 
		{
			dist = tx, ix += idir[0];
			if (ty == tx) iy += idir[1];
			if (tz == tx) iz += idir[2];
		} 
		else if (ty <= tz) 
		{
			dist = ty, iy += idir[1];
			if (tz == ty) iz += idir[2];
		} 
		else dist = tz, iz += idir[2];
	}

	return false;
}