Exemple #1
0
Fichier : ray.cpp Projet : JT-a/USD
bool
GfRay::Intersect(const GfRange3d &box,
		 double *enterDistance, double *exitDistance) const
{
    if (box.IsEmpty())
	return false;

    // Compute the intersection distance of all 6 planes of the
    // box. Save the largest near-plane intersection and the smallest
    // far-plane intersection.
    double maxNearest = -DBL_MAX, minFarthest = DBL_MAX;
    for (size_t i = 0; i < 3; i++) {

        // Skip dimensions almost parallel to the ray.
        double d = GetDirection()[i];
        if (GfAbs(d) < GF_MIN_VECTOR_LENGTH) {
            // ray is parallel to this set of planes.
            // If origin is not between them, no intersection.
            if (GetStartPoint()[i] < box.GetMin()[i] ||
                GetStartPoint()[i] > box.GetMax()[i]) {
                return false;
            } else {
                continue;
            }
        }

        d = 1.0 / d;
        double t1 = d * (box.GetMin()[i] - GetStartPoint()[i]);
        double t2 = d * (box.GetMax()[i] - GetStartPoint()[i]);

        // Make sure t1 is the nearer one
        if (t1 > t2) {
            double tmp = t1;
            t1 = t2;
            t2 = tmp;
        }

        // Update the min and max
        if (t1 > maxNearest)
            maxNearest = t1;
        if (t2 < minFarthest)
            minFarthest = t2;
    }

    // If the largest near-plane intersection is after the smallest
    // far-plane intersection, the ray's line misses the box. Also
    // check if both intersections are completely outside the near/far
    // bounds.
    if (maxNearest  >  minFarthest ||
        minFarthest < 0.0)
        return false;
        
    if (enterDistance)
	*enterDistance = maxNearest;
    if (exitDistance)
        *exitDistance = minFarthest;
    return true;
}
VtVec3fArray
UsdGeomModelAPI::ComputeExtentsHint(
        UsdGeomBBoxCache& bboxCache) const
{
    static const TfTokenVector &purposeTokens =
        UsdGeomImageable::GetOrderedPurposeTokens();

    VtVec3fArray extents(purposeTokens.size() * 2);
    size_t lastNonEmptyBbox = std::numeric_limits<size_t>::max();

    // We should be able execute this loop in parallel since the
    // bounding box computation can be multi-threaded. However, most 
    // conversion processes are run on the farm and are limited to one
    // CPU, so there may not be a huge benefit from doing this. Also, 
    // we expect purpose 'default' to be the most common purpose value 
    // and in some cases the only purpose value. Computing bounds for 
    // the rest of the purpose values should be very fast.
    for(size_t bboxType = purposeTokens.size(); bboxType-- != 0; ) {

        // Set the gprim purpose that we are interested in computing the 
        // bbox for. This doesn't cause the cache to be blown.
        bboxCache.SetIncludedPurposes(
            std::vector<TfToken>(1, purposeTokens[bboxType]));

        GfBBox3d bbox = bboxCache.
            ComputeUntransformedBound(GetPrim());

        const GfRange3d range = bbox.ComputeAlignedBox();

        if (!range.IsEmpty() && lastNonEmptyBbox == std::numeric_limits<size_t>::max())
            lastNonEmptyBbox = bboxType;
        
        const GfVec3d &min = range.GetMin();
        const GfVec3d &max = range.GetMax();

        size_t index = bboxType * 2;
        extents[index] = GfVec3f(min[0], min[1], min[2]);
        extents[index + 1] = GfVec3f(max[0], max[1], max[2]);
    }

    // If all the extents are empty. Author a single empty range.
    if (lastNonEmptyBbox == std::numeric_limits<size_t>::max())
        lastNonEmptyBbox = 0;

    // Shrink the array to only include non-empty bounds. 
    // If all the bounds are empty, we still need to author one empty 
    // bound.
    extents.resize(2 * (lastNonEmptyBbox + 1));
    return extents;
}
Exemple #3
0
bool
GfPlane::IntersectsPositiveHalfSpace(const GfRange3d &box) const
{
    if (box.IsEmpty())
	return false;
    
    // Test each vertex of the box against the positive half
    // space. Since the box is aligned with the coordinate axes, we
    // can test for a quick accept/reject at each stage.

// This macro tests one corner using the given inequality operators.
#define _GF_CORNER_TEST(X, Y, Z, XOP, YOP, ZOP)                               \
    if (X + Y + Z >= _distance)                                               \
        return true;                                                          \
    else if (_normal[0] XOP 0.0 && _normal[1] YOP 0.0 && _normal[2] ZOP 0.0)  \
        return false

    // The sum of these values is GfDot(box.GetMin(), _normal)
    double xmin = _normal[0] * box.GetMin()[0];
    double ymin = _normal[1] * box.GetMin()[1];
    double zmin = _normal[2] * box.GetMin()[2];

    // We can do the all-min corner test right now.
    _GF_CORNER_TEST(xmin, ymin, zmin, <=, <=, <=);

    // The sum of these values is GfDot(box.GetMax(), _normal)
    double xmax = _normal[0] * box.GetMax()[0];
    double ymax = _normal[1] * box.GetMax()[1];
    double zmax = _normal[2] * box.GetMax()[2];

    // Do the other 7 corner tests.
    _GF_CORNER_TEST(xmax, ymax, zmax, >=, >=, >=);
    _GF_CORNER_TEST(xmin, ymin, zmax, <=, <=, >=);
    _GF_CORNER_TEST(xmin, ymax, zmin, <=, >=, <=);
    _GF_CORNER_TEST(xmin, ymax, zmax, <=, >=, >=);
    _GF_CORNER_TEST(xmax, ymin, zmin, >=, <=, <=);
    _GF_CORNER_TEST(xmax, ymin, zmax, >=, <=, >=);
    _GF_CORNER_TEST(xmax, ymax, zmin, >=, >=, <=);

    // CODE_COVERAGE_OFF - We should never get here, but just in case...
    return false;
    // CODE_COVERAGE_ON

#undef _GF_CORNER_TEST
}