コード例 #1
0
/*
====================
sdTraceSurface::RayIntersection
====================
*/
bool sdTraceSurface::RayIntersection( const idVec3& start, const idVec3& end, idDrawVert& dv ) const {
	idVec3			p;
	int				linkNum;
	unsigned int	i;
	unsigned int	maxTraceBins;
	int				hashBin[3];
	int				separatorAxis;
	float			faceDist, traceDist;
	float			separatorDist;
	idVec3			normal, invNormal;

	// clear the result in case nothing is hit
	dv.Clear();

	if ( numLinkBlocks == 0 ) {
		return false;
	}

	// get trace normal and normalize
	normal = end - start;
	faceDist = traceDist = normal.Normalize();

	// inverse normal
	invNormal[0] = ( normal[0] != 0.0f ) ? 1.0f / normal[0] : 1.0f;
	invNormal[1] = ( normal[1] != 0.0f ) ? 1.0f / normal[1] : 1.0f;
	invNormal[2] = ( normal[2] != 0.0f ) ? 1.0f / normal[2] : 1.0f;

	// maximum number of hash bins the trace can go through
	maxTraceBins = 1 + idMath::Ftoi( traceDist * (
							fabs( normal[0] ) * invBinSize[0] +
								fabs( normal[1] ) * invBinSize[1] +
									fabs( normal[2] ) * invBinSize[2] ) );

	// get the first hash bin for the trace
	p = start - _bounds[0];
	hashBin[0] = idMath::Ftoi( idMath::Floor( p[0] * invBinSize[0] ) );
	hashBin[1] = idMath::Ftoi( idMath::Floor( p[1] * invBinSize[1] ) );
	hashBin[2] = idMath::Ftoi( idMath::Floor( p[2] * invBinSize[2] ) );

	separatorAxis = 0;
	separatorDist = 0.0f;

	bool insideHash = false;

	for ( i = 0; i < maxTraceBins; i++, GetNextHashBin( start, normal, hashBin, separatorAxis, separatorDist ) ) {

		// if this bin is outside the valid hash space
		if ( ( hashBin[0] | hashBin[1] | hashBin[2] ) & ~( binsPerAxis - 1 ) ) {
			if ( insideHash ) {
				break;		// left valid hash space
			}
			continue;		// not yet in valid hash space
		}

		insideHash = true;

		// if a triangle was hit before the plane that separates this hash bin from the previous hash bin
		if ( faceDist < traceDist && faceDist < separatorDist * invNormal[separatorAxis] ) {
			break;
		}

		const triLink_t *link;

		// test all the triangles in this hash bin
		for ( linkNum = binLinks[hashBin[0]][hashBin[1]][hashBin[2]]; linkNum != -1; linkNum = link->nextLink ) {
			link = &linkBlocks[ linkNum / MAX_LINKS_PER_BLOCK ][ linkNum % MAX_LINKS_PER_BLOCK ];

			faceDist = TraceToMeshFace( link->faceNum, start, normal, faceDist, traceDist, dv );
		}
	}

	// FIXME: SD_USE_DRAWVERT_SIZE_32
#if defined( SD_USE_DRAWVERT_SIZE_32 )
	idVec3 n = dv.GetNormal();
	n.Normalize();
	dv.SetNormal( n );
#else
	dv._normal.Normalize();
#endif

	return ( faceDist < traceDist );
}