Download

How do you get the top left corner of a rotated vehicle in Unreal Engine 4?

I need to make an AI car. For this, the car needs to have sensors. Those sensors are used to avoid obstacles.
I can’t figure out how to get the top left corner position of the vehicle when it is rotated. The extent, rotation and location of the vehicle is known.

Here is an image of what I mean with sensors:
car with sensors

Here is a video of my current progress (the red line starts at the top left corner, but the start position gets wrong after the car rotates): video

This is my code so far:

 FHitResult OutHit;     FHitResult OutHit2;

    FVector Start = GetVehicleMovementComponent()->GetActorLocation();
    Start += FVector(GetMesh()->GetCachedLocalBounds().GetBox().GetExtent() * GetMesh()->GetComponentRotation().Vector());

    FVector End = (GetMesh()->GetComponentRotation().Vector() * 1000.f) + Start;

    FVector test = GetVehicleMovementComponent()->GetActorLocation();

    test.X += GetMesh()->GetCachedLocalBounds().GetBox().GetExtent().X * GetActorForwardVector().X;
    test.Y -= GetMesh()->GetCachedLocalBounds().GetBox().GetExtent().Y * GetActorForwardVector().Y;
    test.Z -= GetMesh()->GetCachedLocalBounds().GetBox().GetExtent().Z * GetActorForwardVector().Z;

/*    float x = test.X - GetMesh()->GetCachedLocalBounds().GetBox().GetExtent().X;
    float y = test.Y - GetMesh()->GetCachedLocalBounds().GetBox().GetExtent().Y;

    float theta = GetMesh()->GetRelativeRotationCache().GetCachedRotator().Yaw;

    float rotatedX = test.X * cos(theta) - test.Y * sin(theta);
    float rotatedY = test.X * sin(theta) + test.Y * cos(theta);

    test.X = rotatedX + x;
    test.Y = rotatedY + y;  */


    FVector test2 = (GetMesh()->GetComponentRotation().Vector() * 1000.f) + test;

    DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, -1.f, 4, 4.f);
    DrawDebugLine(GetWorld(), test, test2, FColor::Red, false, -1.f, 4, 4.f);

    FCollisionQueryParams CollisionParams;

    bool isHit = GetWorld()->LineTraceSingleByChannel(OutHit, Start, End, ECC_Visibility, CollisionParams);
    bool isHit2 = GetWorld()->LineTraceSingleByChannel(OutHit2, FVector(test), test2, ECC_Visibility, CollisionParams);

    GEngine->AddOnScreenDebugMessage(1, 1, FColor::Green, FString::Printf(TEXT("Rotation Yaw %f"), GetMesh()->GetRelativeRotationCache().GetCachedRotator().Yaw));
    GEngine->AddOnScreenDebugMessage(2, 1, FColor::Red, FString::Printf(TEXT("Rotation Pitch %f"), GetMesh()->GetRelativeRotationCache().GetCachedRotator().Pitch));
    GEngine->AddOnScreenDebugMessage(3, 1, FColor::Yellow, FString::Printf(TEXT("Rotation Roll %f"), GetMesh()->GetRelativeRotationCache().GetCachedRotator().Roll));
    GEngine->AddOnScreenDebugMessage(4, 1, FColor::Green, FString::Printf(TEXT("Forward X %f"), GetActorForwardVector().X));
    GEngine->AddOnScreenDebugMessage(5, 1, FColor::Red, FString::Printf(TEXT("Forward Y %f"), GetActorForwardVector().Y));
    GEngine->AddOnScreenDebugMessage(6, 1, FColor::Yellow, FString::Printf(TEXT("Forward Z %f"), GetActorForwardVector().Z));
    GEngine->AddOnScreenDebugMessage(7, 1, FColor::Green, FString::Printf(TEXT("Pos X %f"), test.X));
    GEngine->AddOnScreenDebugMessage(8, 1, FColor::Red, FString::Printf(TEXT("Pos Y %f"), test.Y));
    GEngine->AddOnScreenDebugMessage(9, 1, FColor::Yellow, FString::Printf(TEXT("Pos Z %f"), test.Z));

    if (isHit)
    {
        if (OutHit.bBlockingHit && OutHit.Actor != nullptr)
        {
            GEngine->AddOnScreenDebugMessage(1, 1, FColor::Red, FString::Printf(TEXT("Intersection with %s"), *OutHit.GetActor()->GetName()));
        }
    }

You might find something a little closer to what you want, if you do, let me know, it might help me out too :slight_smile:

But, what I came up with is using the actual static mesh bounds, rather than the actor bounds, because the actor bounds are axis-aligned, and the static mesh bounds remain static:



FVector origin, extent;
actor->GetActorBounds(true, origin, extent); // to get the center of the entire thing

UStaticMeshComponent* staticMesh = Cast<UStaticMeshComponent>(actor->GetComponentByClass(UStaticMeshComponent::StaticClass());
FVector minBounds, maxBounds;
staticMesh->GetLocalBounds(minBounds, maxBounds); // gets the bounds of the static mesh on the actor -- if you have multiple visual components, or are not using a static mesh, you'll need to change this up

FRotator rotation = actor->GetActorRotation();
FVector forwardDirection, rightDirection, upDirection;
FRotationMatrix(rot).GetScaledAxes(forwardDirection, rightDirection, upDirection); // get direction vectors local to the item

FVector top = upDirection * maxBounds.Z * 0.5;
FVector right = rightDirection * maxBounds.Y;
FVector front = forwardDirection * maxBounds.X;

FVector topRightFront = origin + top + right + front;


In most cases, the car mesh we used may not a symmetry through their origin. So build some sockets on the car and using the pose of sockets would be better.

ah, yes, i forgot about sockets. you can add sockets to skeletals or statics these days. In my particular case, I need to know the actual corners of the mesh boundaries, so that works for me. :smiley: