Get Random Point In Bounding Box Problem If Rotated

Hey guys, I’m having a problem where I want to get a random point in a bounding box (from a box component). Everything goes right if the actor containing the box component not being rotated OR being rotated per 90 degrees (0, 90, 180, 270, etc). If its being rotated like 45 degrees, the bound won’t shape like the actual boxcomponent.

Here’s what I mean.

If the box component is rotated like that, there are some bounds area that is not in the box overlap and that will cause the points outside the boxcomponent. Do you guys have any idea or solution regarding this problem? How can I make it only generate the point inside the BoxComponent even if its rotated like that.

Thank you very much!

It’s a pain in the bum, basically :slight_smile:

The bounds calculation is correct, so we need to calculate via a box the doesn’t rotate with the actor, and then correct.

I have two components, one that always corrects to zero rotation when I move the actor

image

We need to find the points in the unrotated box, and do a couple of transforms to get the rotated box

It works.

The random point node gives you world coordinates, not much use here. So we have to make them local, rotate them by the amount the actor is rotated, and then make them world again :slight_smile:

rotatedbounds

2 Likes

Hello @ClockworkOcean ,

I think it’s different from my case, I also try your way but it still generated out of the box (Or I’m the one that implemented it wrong).

image
I want to generate some point inside the BoxComponent (which is the brown box), when I use GetRandomPointInBoundingBox, it’s generated also outside the box, when I try to check the Origin and Extent using DrawDebugBox, I can see the problem that the bounds itself (which is the blue box one) is not the same shape as the BrownBox. My code is simple:

const FVector& Origin = Area->Bounds.Origin;
const FVector& BoxExtent = Area->Bounds.BoxExtent;

// Get Random Point In Bounding Box
const FVector BoxMin = Origin - BoxExtent; 
const FVector BoxMax = Origin + BoxExtent;	
FVector RandomPoint = FMath::RandPointInBox(FBox(BoxMin, BoxMax));

DrawDebugBox(GetWorld(), Origin, BoxExtent, FColor::Blue, false, 200.f);

So I don’t know how to only generate the point inside the BrownBox (since using the Bounds don’t work because the bound shape isn’t the same). The bound shape gone wrong IF the actor is rotated like 50 degrees or some degrees that not 90,180,270,etc. If the actor is rotated 90 degrees and likely, the bounds is perfect.
image

Since I need some to be rotated like 50 degrees to fit the map, I don’t know how.

I also try your code:

const FVector Inversed = GetActorTransform().InverseTransformPosition(RandomPoint);
const FVector Rotated = GetActorRotation().RotateVector(Inversed);
const FVector TransformLocation = GetActorTransform().TransformPosition(Rotated);

DrawDebugSphere(GetWorld(), TransformLocation, 20.f, 5, FColor::Green, false, 200.f);

And as you can see in both of the image, the green sphere will be correct if the bounds is correct. Do you have any idea about this?

Thanks, I appreciate your answer.

1 Like

Maybe get it working in BP first, then at least we keep the variables pinned down a bit :slight_smile:

What is critical with my approach, is I get the points in an unrotated box, and then transform them.

I don’t see anything about an unrotated box here? ( could be missing it ). So we have the actor rotation, but we also have a box ( same size as the rotated box ) that never rotates with the actor, because the construction script always holds it to zero. That’s the box we find the random points in.

1 Like

Try this


FVector ARotBox::GetRandomInRotated() 
{	
	FVector rotatedVec = FVector::Zero();	
	if (UnrotatedBox != nullptr) {

		UnrotatedBox->SetWorldRotation(FRotator::ZeroRotator);		
		FVector RandomPoint = FMath::RandPointInBox(UnrotatedBox->Bounds.GetBox());				
		FMatrix LocalToWorldInverse = GetActorTransform().ToMatrixWithScale();		

		rotatedVec = UKismetMathLibrary::GreaterGreater_VectorRotator(LocalToWorldInverse.GetOrigin() - RandomPoint, LocalToWorldInverse.Rotator()) + GetActorLocation();
		DrawDebugBox(GetWorld(), GetActorLocation(), UnrotatedBox->Bounds.BoxExtent, FColor::Blue, false, 20000.f);		
		DrawDebugBox(GetWorld(), GetActorLocation(), UnrotatedBox->Bounds.BoxExtent, GetActorRotation().Quaternion(), FColor::Red, false, 20000.f);
	}
	return rotatedVec;
}

2 Likes

Thank you very much you guys @ClockworkOcean @3dRaven , now it’s working!
image

also could you explain a little bit about your code like why I have to inverse it first before rotating it?

1 Like

Its actually not iversed it’s just an old var name that i used & forgot to change (previously it had .Inverse() at the end)

but that would cause the tansform to flip. So its just direct work with fmatrix.

I see, thanks again!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.