FVector UKismetMathLibrary::LessLess_VectorRotator(FVector A, FRotator B) { return B.UnrotateVector(A); }
static void CalcBoundingSphyl(const FRawMesh& RawMesh, FSphere& sphere, float& length, FRotator& rotation, FVector& LimitVec) { if (RawMesh.VertexPositions.Num() == 0) return; FVector Center, Extents; CalcBoundingBox(RawMesh, Center, Extents, LimitVec); // @todo sphere.Center could perhaps be adjusted to best fit if model is non-symmetric on it's longest axis sphere.Center = Center; // Work out best axis aligned orientation (longest side) float Extent = Extents.GetMax(); if (Extent == Extents.X) { rotation = FRotator(90.f, 0.f, 0.f); Extents.X = 0.0f; } else if (Extent == Extents.Y) { rotation = FRotator(0.f, 0.f, 90.f); Extents.Y = 0.0f; } else { rotation = FRotator(0.f, 0.f, 0.f); Extents.Z = 0.0f; } // Cleared the largest axis above, remaining determines the radius float r = Extents.GetMax(); float r2 = FMath::Square(r); // Now check each point lies within this the radius. If not - expand it a bit. for (uint32 i = 0; i<(uint32)RawMesh.VertexPositions.Num(); i++) { FVector cToP = (RawMesh.VertexPositions[i] * LimitVec) - sphere.Center; cToP = rotation.UnrotateVector(cToP); const float pr2 = cToP.SizeSquared2D(); // Ignore Z here... // If this point is outside our current bounding sphere's radius if (pr2 > r2) { // ..expand radius just enough to include this point. const float pr = FMath::Sqrt(pr2); r = 0.5f * (r + pr); r2 = FMath::Square(r); } } // The length is the longest side minus the radius. float hl = FMath::Max(0.0f, Extent - r); // Now check each point lies within the length. If not - expand it a bit. for (uint32 i = 0; i<(uint32)RawMesh.VertexPositions.Num(); i++) { FVector cToP = (RawMesh.VertexPositions[i] * LimitVec) - sphere.Center; cToP = rotation.UnrotateVector(cToP); // If this point is outside our current bounding sphyl's length if (FMath::Abs(cToP.Z) > hl) { const bool bFlip = (cToP.Z < 0.f ? true : false); const FVector cOrigin(0.f, 0.f, (bFlip ? -hl : hl)); const float pr2 = (cOrigin - cToP).SizeSquared(); // If this point is outside our current bounding sphyl's radius if (pr2 > r2) { FVector cPoint; FMath::SphereDistToLine(cOrigin, r, cToP, (bFlip ? FVector(0.f, 0.f, 1.f) : FVector(0.f, 0.f, -1.f)), cPoint); // Don't accept zero as a valid diff when we know it's outside the sphere (saves needless retest on further iterations of like points) hl += FMath::Max(FMath::Abs(cToP.Z - cPoint.Z), 1.e-6f); } } } sphere.W = r; length = hl * 2.0f; }