123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- #include "qrad.h"
- #define NUM_LERP_POINTS 4 //used by PointInWall (defines magic number)
- //===============================================
- // PointInEdge - base for all boundary checks
- //===============================================
- inline bool PointInEdge(const vec_t* const point, const vec_t* const p1, const vec_t* const p2, const vec_t* const normal)
- {
- vec3_t edge, temp, temp2; //don't make static because we need multithread support
- VectorSubtract(p1,p2,edge);
- VectorSubtract(p1,point,temp);
- CrossProduct(edge,temp,temp2);
- //old code normalizes here, which is useless when detecting sign change below
- return (DotProduct(temp2,normal) >= 0);
- }
- //===============================================
- // PointInWall - check a lerpWall_t boundary
- //===============================================
- inline bool PointInWall(const lerpWall_t* const wall, const vec_t* const point)
- {
- for(int counter = 0; counter < NUM_LERP_POINTS; counter++)
- {
- if(!PointInEdge(point,wall->vertex[counter],wall->vertex[(counter+1)%4],wall->plane.normal))
- { return false; }
- }
- return true;
- }
- //===============================================
- // PointInWall - check a Winding boundary
- //===============================================
- inline bool PointInWinding(const Winding* const W, const dplane_t* const plane, const vec_t* const point)
- {
- //reverse direction of points because plane input is 180 degrees from desired normal
- for(size_t counter = 0; counter < W->m_NumPoints-1; counter++)
- {
- if(!PointInEdge(point,W->m_Points[counter+1],W->m_Points[counter],plane->normal))
- { return false; }
- }
- return PointInEdge(point,W->m_Points[0],W->m_Points[W->m_NumPoints-1],plane->normal);
- }
- //==================================================
- // PointInTri - check a boundary defined by 3 points
- //==================================================
- inline bool PointInTri(const vec_t* const point, const dplane_t* const plane, const vec_t* const p1, const vec_t* const p2, const vec_t* const p3)
- {
- return (PointInEdge(point,p1,p2,plane->normal) && PointInEdge(point,p2,p3,plane->normal) && PointInEdge(point,p3,p1,plane->normal));
- }
- //==================================================
- // LineSegmentIntersectsBounds - does the line pass through the box?
- //==================================================
- inline bool LineSegmentIntersectsBounds(const vec_t* const p1, const vec_t* const p2, const vec3_t& mins, const vec3_t& maxs)
- {
- vec_t tNear = -999999999;
- vec_t tFar = 999999999;
- vec_t t0,t1,tmp;
- vec3_t d;
- VectorSubtract(p2,p1,d);
- for(int index = 0; index < 3; ++index)
- {
- if(fabs(d[index]) < EQUAL_EPSILON)
- {
- if(p1[index] < (mins[index] - EQUAL_EPSILON) || p1[index] > (maxs[index] + EQUAL_EPSILON))
- {
- return false;
- }
- continue;
- }
- t0 = (mins[index] - p1[index]) / d[index];
- t1 = (maxs[index] - p1[index]) / d[index];
- if(t0 > t1)
- {
- tmp = t1;
- t1 = t0;
- t0 = tmp;
- }
- if(t0 > tNear)
- {
- tNear = t0;
- }
- if(t1 < tFar)
- {
- tFar = t1;
- }
- if(tNear > tFar || tFar < 0)
- {
- return false;
- }
- }
- return true;
- }
- //==================================================
- // LineSegmentIntersectsFace - does the face block the segment?
- //==================================================
- inline bool LineSegmentIntersectsFace(const vec_t* const p1, const vec_t* const p2, vec3_t& point_out, const int index)
- {
- if(LineSegmentIntersectsBounds(p1,p2,g_opaque_face_list[index].mins,g_opaque_face_list[index].maxs))
- {
- if(LineSegmentIntersectsPlane(g_opaque_face_list[index].plane,p1,p2,point_out))
- {
- if(PointInWinding(g_opaque_face_list[index].winding,&g_opaque_face_list[index].plane,point_out))
- {
- return true;
- }
- }
- }
- return false;
- }
- //==================================================
- // LineSegmentIntersectsPlane - returns intersection
- // point in point parameter if it exists
- //==================================================
- inline bool LineSegmentIntersectsPlane(const dplane_t& plane, const vec_t* const p1, const vec_t* const p2, vec3_t& point)
- {
- vec3_t line;
- VectorSubtract(p2,p1,line);
- vec_t dist1 = DotProduct(plane.normal,line); //p1 to p2
- if(dist1 == 0.0) //parallel
- { return false; }
- vec3_t origin;
- VectorScale(plane.normal,plane.dist,origin);
- VectorSubtract(origin,p1,origin);
- vec_t loc = DotProduct(plane.normal,origin)/dist1; //p1 to plane
- if(loc < 0 || loc > 1) //if we're over 100% or
- { return false; } //under 0% of original length
- VectorMA(p1,loc,line,point);
- return true;
- }
- //==================================================
- // PlaneFromPoints
- //==================================================
- inline void PlaneFromPoints(const vec_t* const p1, const vec_t* const p2, const vec_t* const p3, dplane_t* plane)
- {
- vec3_t temp, temp2;
- VectorSubtract(p3,p2,temp);
- VectorSubtract(p1,p2,temp2);
- CrossProduct(temp,temp2,plane->normal);
- VectorNormalize(plane->normal);
- plane->dist = DotProduct(plane->normal,p1);
- }
- //==================================================
- // SnapToPlane
- //==================================================
- inline void SnapToPlane(const dplane_t* const plane, vec_t* const point, const vec_t offset)
- {
- vec_t scale = (plane->dist + offset);
- scale -= DotProduct(plane->normal,point);
- VectorMA(point,scale,plane->normal,point);
- }
- // =====================================================================================
- // TestSegmentAgainstOpaqueList
- // Returns facenum of the opaque face if the segment intersects an item in the opaque list
- // =====================================================================================
- #ifdef HLRAD_HULLU
- int TestSegmentAgainstOpaqueList(const vec_t* p1, const vec_t* p2, vec3_t &scaleout)
- #else
- int TestSegmentAgainstOpaqueList(const vec_t* p1, const vec_t* p2)
- #endif
- {
- unsigned x;
- vec3_t point;
- const dplane_t* plane;
- const Winding* winding;
- int returnVal = -1;
- int facenum;
- //vec_t* endpoint;
- bool blocked = false;
- //*endpoint = *p2;
- #ifdef HLRAD_HULLU
- VectorFill(scaleout,1.0);
- #endif
- for (x = 0; x < g_opaque_face_count; x++)
- {
- plane = &g_opaque_face_list[x].plane;
- winding = g_opaque_face_list[x].winding;
- facenum = g_opaque_face_list[x].facenum;
- // if(LineSegmentIntersectsFace(p1,endpoint,point,x))
- if(LineSegmentIntersectsFace(p1,p2,point,x))
- {
- #ifdef HLRAD_HULLU
- if(g_opaque_face_list[x].transparency)
- {
- VectorMultiply(scaleout, g_opaque_face_list[x].transparency_scale, scaleout);
- //don't change endpoint here -- only if face completely blocks light
- }
- else
- {
- //can't break here because we might be blocked more than one time,
- //continue searching for earliest blocking face
- //*endpoint = *point;
- returnVal = facenum;
- blocked = true;
- }
- #else
- *endpoint = *point;
- returnVal = facenum;
- blocked = true;
- #endif
- }
- }
- if(blocked)
- {
- return returnVal; //return face that intersects the segment closest to p1
- }
- #ifdef HLRAD_HULLU
- if(VectorCompare(scaleout,vec3_origin))
- {
- VectorClear(scaleout);
- }
- #endif
- return -1; //not completely blocked
- }
|