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; }
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 }