bool UsdGeomPointBased::ComputeExtent(const VtVec3fArray& points, VtVec3fArray* extent) { // Create Sized Extent extent->resize(2); // Calculate bounds GfRange3d bbox; TF_FOR_ALL(pointsItr, points) { bbox.UnionWith(GfVec3f(*pointsItr)); }
bool UsdGeomPointInstancer::ComputeExtentAtTime( VtVec3fArray* extent, const UsdTimeCode time, const UsdTimeCode baseTime) const { if (!extent) { TF_WARN("%s -- null container passed to ComputeExtentAtTime()", GetPrim().GetPath().GetText()); return false; } VtIntArray protoIndices; if (!GetProtoIndicesAttr().Get(&protoIndices, time)) { TF_WARN("%s -- no prototype indices", GetPrim().GetPath().GetText()); return false; } const std::vector<bool> mask = ComputeMaskAtTime(time); if (!mask.empty() && mask.size() != protoIndices.size()) { TF_WARN("%s -- mask.size() [%zu] != protoIndices.size() [%zu]", GetPrim().GetPath().GetText(), mask.size(), protoIndices.size()); return false; } const UsdRelationship prototypes = GetPrototypesRel(); SdfPathVector protoPaths; if (!prototypes.GetTargets(&protoPaths) || protoPaths.empty()) { TF_WARN("%s -- no prototypes", GetPrim().GetPath().GetText()); return false; } // verify that all the protoIndices are in bounds. TF_FOR_ALL(iter, protoIndices) { const int protoIndex = *iter; if (protoIndex < 0 || static_cast<size_t>(protoIndex) >= protoPaths.size()) { TF_WARN("%s -- invalid prototype index: %d. Should be in [0, %zu)", GetPrim().GetPath().GetText(), protoIndex, protoPaths.size()); return false; } } // Note that we do NOT apply any masking when computing the instance // transforms. This is so that for a particular instance we can determine // both its transform and its prototype. Otherwise, the instanceTransforms // array would have masked instances culled out and we would lose the // mapping to the prototypes. // Masked instances will be culled before being applied to the extent below. VtMatrix4dArray instanceTransforms; if (!ComputeInstanceTransformsAtTime(&instanceTransforms, time, baseTime, IncludeProtoXform, IgnoreMask)) { TF_WARN("%s -- could not compute instance transforms", GetPrim().GetPath().GetText()); return false; } UsdStageWeakPtr stage = GetPrim().GetStage(); const TfTokenVector purposes { UsdGeomTokens->default_, UsdGeomTokens->proxy, UsdGeomTokens->render }; UsdGeomBBoxCache bboxCache(time, purposes); bboxCache.SetTime(time); GfRange3d extentRange; for (size_t instanceId = 0; instanceId < protoIndices.size(); ++instanceId) { if (!mask.empty() && !mask[instanceId]) { continue; } const int protoIndex = protoIndices[instanceId]; const SdfPath& protoPath = protoPaths[protoIndex]; const UsdPrim& protoPrim = stage->GetPrimAtPath(protoPath); // Get the prototype bounding box. GfBBox3d thisBounds = bboxCache.ComputeUntransformedBound(protoPrim); // Apply the instance transform. thisBounds.Transform(instanceTransforms[instanceId]); extentRange.UnionWith(thisBounds.ComputeAlignedRange()); } const GfVec3d extentMin = extentRange.GetMin(); const GfVec3d extentMax = extentRange.GetMax(); *extent = VtVec3fArray(2); (*extent)[0] = GfVec3f(extentMin[0], extentMin[1], extentMin[2]); (*extent)[1] = GfVec3f(extentMax[0], extentMax[1], extentMax[2]); return true; }