Esempio n. 1
0
//-------------------------------------------------------
std::pair<bool, Ogre::Vector3> Ground::GetIntersectionLocalSpace(const Ogre::Ray & ray) const
{
    if (ray.intersects(mGlobalBoundingBox).first)
    {
        float intersection = -1.0f;
        for (const auto & region : mEntities)
        {
            auto hit = ray.intersects(region->getBoundingBox());
            if (hit.first)
            {
                auto meshHit = GetVertexIntersection(ray, region->getMesh()->getSubMesh(0));
                if (meshHit.first && (intersection < 0.0f || meshHit.second < intersection))
                {
                    intersection = meshHit.second;
                }
            }
        }
        if (intersection >= 0.0f)
        {
            return std::make_pair(true, ray.getPoint(intersection));
        }
    }
    return std::make_pair(false, Ogre::Vector3::ZERO);
}
Esempio n. 2
0
int IntrBox3Sphere3<Real>::FindVertexRegionIntersection (Real ex, Real ey,
    Real ez, Real cx, Real cy, Real cz, Real vx, Real vy, Real vz,
    Real& ix, Real& iy, Real& iz)
{
    // Assumes the sphere is above the vertex +ex, +ey, +ez.

    Real dx = cx - ex;
    Real dy = cy - ey;
    Real dz = cz - ez;
    Real rsqr = mSphere->Radius*mSphere->Radius;
    Real diff = dx*dx + dy*dy + dz*dz - rsqr;
    if (diff <= (Real)0)
    {
        // Sphere is already intersecting the box.
        mContactTime = (Real)0;
        return -1;
    }

    if (vx*dx + vy*dy + vz*dz >= (Real)0)
    {
        // Sphere not moving towards box.
        return 0;
    }

    // The box can be divided up into 3 regions, which simplifies checking to
    // see what the sphere hits.  The regions are divided by which edge
    // (formed by the vertex and some axis) is closest to the velocity
    // vector.
    //
    // To check if it hits the vertex, look at the edge (E) it is going
    // towards.  Create a plane formed by the other two edges (with E as the
    // plane normal) with the vertex at the origin.  The intercept along an
    // axis, in that plane, of the line formed by the sphere center and the
    // velocity as its direction, will be fCrossAxis/fVEdge.  Thus, the
    // distance from the origin to the point in the plane that that line from
    // the sphere in the velocity direction crosses will be the squared sum
    // of those two intercepts.  If that sum is less than the radius squared,
    // then the sphere will hit the vertex otherwise, it will continue on
    // past the vertex.  If it misses, since it is known which edge the box
    // is near, the find edge region test can be used.
    //
    // Also, due to the constrained conditions, only those six cases (two for
    // each region, since fCrossEdge can be + or -) of signs of fCross values
    // can occur.
    //
    // The 3rd case will also pick up cases where D = V, causing a ZERO cross.

    Real crossX = vy*dz - vz*dy;
    Real crossY = vx*dz - vz*dx;
    Real crossZ = vy*dx - vx*dy;
    Real crX2 = crossX*crossX;
    Real crY2 = crossY*crossY;
    Real crZ2 = crossZ*crossZ;
    Real vx2 = vx*vx;
    Real vy2 = vy*vy;
    Real vz2 = vz*vz;

    // Intersection with the vertex?
    if ((crossY <  (Real)0 && crossZ >= (Real)0 && crY2 + crZ2 <= rsqr*vx2)
    ||  (crossZ <  (Real)0 && crossX <  (Real)0 && crX2 + crZ2 <= rsqr*vy2)
    ||  (crossY >= (Real)0 && crossX >= (Real)0 && crX2 + crY2 <= rsqr*vz2))
    {
        // Standard line-sphere intersection.
        mContactTime = GetVertexIntersection(dx, dy, dz, vx, vy, vz,
            mSphere->Radius*mSphere->Radius);
        ix = mContactTime*vx + cx;
        iy = mContactTime*vy + cy;
        iz = mContactTime*vz + cz;
        return 1;
    }
    else if (crossY < (Real)0 && crossZ >= (Real)0)
    {
        // x edge region, check y,z planes.
        return FindEdgeRegionIntersection(ey, ex, ez, cy, cx, cz, vy, vx,
            vz, iy, ix, iz, false);
    }
    else if (crossZ < (Real)0 && crossX < (Real)0)
    {
        // y edge region, check x,z planes.
        return FindEdgeRegionIntersection(ex, ey, ez, cx, cy, cz, vx, vy,
            vz, ix, iy, iz, false);
    }
    else // crossY >= 0 && crossX >= 0
    {
        // z edge region, check x,y planes.
        return FindEdgeRegionIntersection(ex, ez, ey, cx, cz, cy, vx, vz,
            vy, ix, iz, iy, false);
    }
}
Esempio n. 3
0
int IntrBox3Sphere3<Real>::FindJustEdgeIntersection (Real cy, Real ex,
    Real ey, Real ez, Real dx, Real dz, Real vx, Real vy, Real vz,
    Real& ix, Real& iy, Real& iz)
{
    // Finds the intersection of a point dx and dz away from an edge with
    // direction y.  The sphere is at a point cy, and the edge is at the
    // point ex.  Checks the edge and the vertex the velocity is heading
    // towards.

    Real rsqr = mSphere->Radius*mSphere->Radius;
    Real dy, crossZ, crossX;  // possible edge/vertex intersection
    int signY;

    // Depending on the sign of Vy, pick the vertex that the velocity is
    // heading towards on the edge, as well as creating crossX and crossZ
    // such that their sign will always be positive if the sphere center goes
    // over that edge.

    if (vy >= (Real)0)
    {
        signY = 1;
        dy = cy - ey;
        crossZ = dx*vy - dy*vx;
        crossX = dz*vy - dy*vz;
    }
    else
    {
        signY = -1;
        dy = cy + ey;
        crossZ = dy*vx - dx*vy;
        crossX = dy*vz - dz*vy;
    }

    // Check where on edge this intersection will occur.
    if (crossZ >= (Real)0 && crossX >= (Real)0
    &&  crossX*crossX + crossZ*crossZ >
        vy*vy*mSphere->Radius*mSphere->Radius)
    {
        // Sphere potentially intersects with vertex.
        Vector3<Real> relVelocity(vx, vy, vz);
        Vector3<Real> D(dx, dy, dz);
        Vector3<Real> cross = D.Cross(relVelocity);
        if (cross.SquaredLength() > rsqr*relVelocity.SquaredLength())
        {
            // Sphere overshoots the box on the vertex.
            return 0;
        }

        // Sphere actually does intersect the vertex.
        mContactTime = GetVertexIntersection(dx, dy, dz, vx, vy, vz, rsqr);
        ix = ex;
        iy = signY*ey;
        iz = ez;
    }
    else
    {
        // Sphere intersects with edge.
        Real vsqrX = vz*vz + vx*vx;
        mContactTime = GetEdgeIntersection(dx, dz, vx, vz, vsqrX, rsqr);
        ix = ex;
        iy = cy + mContactTime*vy;
        iz = ez;
    }
    return 1;
}
Esempio n. 4
0
int IntrBox3Sphere3<Real>::FindFaceRegionIntersection (Real ex, Real ey,
    Real ez, Real cx, Real cy, Real cz, Real vx, Real vy, Real vz,
    Real& ix, Real& iy, Real& iz, bool aboveFace)
{
    // Returns when and whether a sphere in the region above face +Z
    // intersects face +Z or any of its vertices or edges.  The input
    // aboveFace is true when the x and y coordinates are within the x and y
    // extents.  The function will still work if they are not, but it needs
    // to be false then, to avoid some checks that assume that x and y are
    // within the extents.  This function checks face z, and the vertex and
    // two edges that the velocity is headed towards on the face.

    // Check for already intersecting if above face.
    if (cz <= ez + mSphere->Radius && aboveFace)
    {
        mContactTime = (Real)0;
        return -1;
    }

    // Check for easy out (moving away on Z axis).
    if (vz >= (Real)0)
    {
        return 0;
    }

    Real rsqr = mSphere->Radius*mSphere->Radius;

    Real vsqrX = vz*vz + vx*vx;
    Real vsqrY = vz*vz + vy*vy;
    Real dx, dy, dz = cz - ez;
    Real crossX, crossY;
    int signX, signY;

    // This determines which way the box is heading and finds the values of
    // CrossX and CrossY which are positive if the sphere center will not
    // pass through the box.  Then it is only necessary to check two edges,
    // the face and the vertex for intersection.

    if (vx >= (Real)0)
    {
        signX = 1;
        dx = cx - ex;
        crossX = vx*dz - vz*dx;
    }
    else
    {
        signX = -1;
        dx = cx + ex;
        crossX = vz*dx - vx*dz;
    }

    if (vy >= (Real)0)
    {
        signY = 1;
        dy = cy - ey;
        crossY = vy*dz - vz*dy;
    }
    else
    {
        signY = -1;
        dy = cy + ey;
        crossY = vz*dy - vy*dz;
    }

    // Does the circle intersect along the x edge?
    if (crossX > mSphere->Radius*vx*signX)
    {
        if (crossX*crossX > rsqr*vsqrX)
        {
            // Sphere overshoots box on the x-axis (either side).
            return 0;
        }

        // Does the circle hit the y edge?
        if (crossY > mSphere->Radius*vy*signY)
        {
            // Potential vertex intersection.
            if (crossY*crossY > rsqr*vsqrY)
            {
                // Sphere overshoots box on the y-axis (either side).
                return 0;
            }

            Vector3<Real> relVelocity(vx,vy,vz);
            Vector3<Real> D(dx,dy,dz);
            Vector3<Real> cross = D.Cross(relVelocity);
            if (cross.SquaredLength() > rsqr*relVelocity.SquaredLength())
            {
                // Sphere overshoots the box on the corner.
                return 0;
            }

            mContactTime = GetVertexIntersection(dx, dy, dz, vx, vy, vz,
                rsqr);
            ix = ex*signX;
            iy = ey*signY;
        }
        else
        {
            // x-edge intersection
            mContactTime = GetEdgeIntersection(dx, dz, vx, vz, vsqrX, rsqr);
            ix = ex*signX;
            iy = cy + vy*mContactTime;
        }
    }
    else
    {
        // Does the circle hit the y edge?
        if (crossY > mSphere->Radius*vy*signY)
        {
            // Potential y-edge intersection.
            if (crossY*crossY > rsqr*vsqrY)
            {
                // Sphere overshoots box on the y-axis (either side).
                return 0;
            }

            mContactTime = GetEdgeIntersection(dy, dz, vy, vz, vsqrY, rsqr);
            ix = cx + vx*mContactTime;
            iy = ey*signY;
        }
        else
        {
            // Face intersection (easy).
            mContactTime = (-dz + mSphere->Radius)/vz;
            ix = mContactTime*vx + cx;
            iy = mContactTime*vy + cy;
        }
    }

    // z coordinate of any intersection must be the face of z.
    iz = ez;
    return 1;
}