/* ============ idSurface_Patch::LerpVert ============ */ void idSurface_Patch::LerpVert( const idDrawVert& a, const idDrawVert& b, idDrawVert& out ) const { out.xyz[0] = 0.5f * ( a.xyz[0] + b.xyz[0] ); out.xyz[1] = 0.5f * ( a.xyz[1] + b.xyz[1] ); out.xyz[2] = 0.5f * ( a.xyz[2] + b.xyz[2] ); out.SetNormal( ( a.GetNormal() + b.GetNormal() ) * 0.5f ); out.SetTexCoord( ( a.GetTexCoord() + b.GetTexCoord() ) * 0.5f ); }
/* ==================== 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 ); }