예제 #1
0
파일: XMath.cpp 프로젝트: 373137461/OBS
BOOL Plane::GetTriplePlaneIntersection(const Plane &p2, const Plane &p3, Vect &intersection) const
{
    Vect rayOrigin, rayDir;

    if(GetDoublePlaneIntersection(p2, rayOrigin, rayDir))
    {
        float fT;
        if(p3.GetRayIntersection(rayOrigin, rayDir, fT))
        {
            intersection = rayOrigin + (rayDir*fT);
            return TRUE;
        }
    }

    return FALSE;
}
예제 #2
0
파일: XMath.cpp 프로젝트: 373137461/OBS
// 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;
}