Beispiel #1
0
BOOL Plane::GetIntersection(const Vect &p1, const Vect &p2, float &fT) const
{
    float P1Dist = p1.DistFromPlane(*this);
    float P2Dist = p2.DistFromPlane(*this);

    if(CloseFloat(P1Dist, 0.0f, EPSILON))
    {
        if(P2Dist == 0.0f)
            return 0;

        fT = 0.0f;
        return 1;
    }
    else if(CloseFloat(P2Dist, 0.0f, EPSILON))
    {
        fT = 1.0f;
        return 1;
    }

    BOOL bP1Over = (P1Dist > 0.0f);
    BOOL bP2Over = (P2Dist > 0.0f);

    if(bP1Over == bP2Over)
        return FALSE;

    float P1AbsDist = fabs(P1Dist);
    float dist2 = (P1AbsDist+fabs(P2Dist));
    if(dist2 < EPSILON)
        return FALSE;
    fT = P1AbsDist/dist2;

    return TRUE;
}
Beispiel #2
0
BOOL PointOnFiniteLine(const Vect &lineV1, const Vect &lineV2, const Vect &p)
{
    Vect line = lineV2-lineV1;
    float lineDist = line.Len();

    Plane plane;
    plane.Dir  = line*(1.0f/lineDist);
    plane.Dist = plane.Dir.Dot(lineV1);

    float dist = p.DistFromPlane(plane);
    if((dist < 0.0f) || (dist > lineDist))
        return FALSE;

    float fT = (dist/lineDist);

    return p.CloseTo(Lerp(lineV1, lineV2, fT));
}
Beispiel #3
0
// yes, I realize this breaks on caps when the ray origin is inside the cylinder.
// it's not like it's actually going to be in there anyway.
BOOL CylinderRayCollision(const Vect &center, float radius, float height, const Vect &rayOrig, const Vect &rayDir, Vect *collision, Plane *collisionPlane)
{
    Vect collisionValue;
    BOOL bHit = FALSE;
    float fT;

    Plane axisPlane(0.0f, 1.0f, 0.0f, center.y);

    //---------------------------------------
    // test the cap
    if(fabs(rayDir.y) > EPSILON)
    {
        BOOL bUnder = (rayDir.y<0.0f);

        Plane planeCap;
        planeCap.Dir.Set(0.0f, bUnder ? 1.0f : -1.0f, 0.0f);
        planeCap.Dist = (bUnder ? center.y : -center.y)+height;

        if(rayOrig.DistFromPlane(planeCap) > 0.0f)
        {
            if(planeCap.GetRayIntersection(rayOrig, rayDir, fT))
            {
                collisionValue = rayOrig+(rayDir*fT);
                Vect CapCenter = center+(planeCap.Dir*height);

                if(collisionValue.Dist(CapCenter) <= radius)
                {
                    if(collisionPlane)
                        *collisionPlane = planeCap;
                    bHit = TRUE;
                }
            }
        }
    }

    if(!bHit && ((1.0f-fabs(rayDir.y)) > EPSILON))
    {
        //---------------------------------------
        // test the body
        Vect adjDir, adjCenter;

        adjDir.Set(rayDir.x, 0.0f, rayDir.z).Norm();
        adjCenter.Set(center.x, rayOrig.y, center.z);

        Vect l   = (adjCenter-rayOrig);
        float d  = l | adjDir;          //distance from adjDir Plane
        float l2 = l | l;               //c-o distance squared
        float r2 = radius*radius;

        if(l2 < r2)                     //if inside the cylinder, fail
            return FALSE;

        if((d < 0.0f) && (l2 > r2))     //if the plane distance is negative, and
            return FALSE;               //the distance is over the radius, fail

        float m2 = l2 - (d*d);          //distance from the cylinder center to
                                        //the closest ray point

        if(m2 > r2)                     //if m2 is larger than the radius, fail
            return FALSE;

        float q = sqrt(r2-m2);          //real distance from the edge of the
                                        //cylinder to the cloest ray point
                                        //(forms a sort of triangle)

        fT = (l2 > r2) ? (d-q) : (d+q); //if the distance is over the radius,
                                        //d-q = T, else d+q=T
                                        //distance

        fT /= (adjDir|rayDir);          //divide by angle to get the proper
                                        //value

        collisionValue = rayOrig+(rayDir*fT);

        if(fabs(collisionValue.DistFromPlane(axisPlane)) >= height)
            return FALSE;

        if(collisionPlane)
        {
            Vect temp = collisionValue;
            temp.y = center.y;

            collisionPlane->Dir  = (temp-center).Norm();
            collisionPlane->Dist = collisionPlane->Dir|temp;
        }

        bHit = TRUE;
    }

    if(!bHit)
        return FALSE;

    if(collision)
        *collision = collisionValue;

    return TRUE;
}