Switching pawn between orbiting and flying

Hi!

I’m trying to realize a custom pawn for visualization purposes. Pawn should have two modes: orbiting and flying.
In flying mode, user can move in all directions and control the camera rotation.
In orbiting mode, mouse movement is used to rotate the pawn around an object, camera is always looking at the model.

There were no problems with flying mode, I made it by placing this code in the Tick method:



FVector NewLocation = GetActorLocation() +
                (OurCamera->GetForwardVector()*CurrentVelocity.X +
                    OurCamera->GetRightVector()*CurrentVelocity.Y)*DeltaTime*MoveSpeed;
            SetActorLocation(NewLocation);

            AddControllerYawInput(CurrentRotation.X);
            AddControllerPitchInput(CurrentRotation.Y);


Where CurrentVelocity contains the scale values from input.

My actual realization of orbiting mode:



MoveDirection = (OurCamera->GetRightVector()*CurrentRotation.X
                + OurCamera->GetUpVector()*CurrentRotation.Y);


            FVector NewLocation = GetActorLocation() + MoveDirection*DeltaTime*rotSpeed;

            FRotator rot = (target - GetActorLocation()).Rotation();
            SetActorLocation(NewLocation);
            GetController()->SetControlRotation(rot);


The idea behind orbiting is very simple: I get mouse input and save the result in CurrentRotation (it is clamped to -1.0,…,1.0). Then I use this values to calculate the offset from my current position, move my pawn there and update controller rotation so the camera is watching at the target point.

Unfortunately, this solution has some problems. The “rotation speed” variable is in unreal units, not in degrees or radians. It means that the rotation speed near the target is much bigger than the rotation speed at, for example, 500 unreal units distance. Also this rotation technique is not very smooth (if to set higher values for rotation speed).

I searched for the solutions in the blueprint section, but most of them use springarms. In my project I have to focus on different targets, so I think that springarms don’t work in my case. Making pawn a child for my viewing model is also a bad idea :slight_smile:
The simplest solution is to include model in a pawn and add springarm to it, but having every statue or car as a pawn and posessing between them is is not a good design pattern :slight_smile:

Could you give me an advice about my problem? What is the optimal solution in my case?

With best regards,
SharpCoder

The problem was solved by using some vector maths :slight_smile:



                FVector radiusVector = GetActorLocation() - target->GetActorLocation();

                FVector CrossProd = FVector::CrossProduct(radiusVector, target->GetActorUpVector());
                CrossProd.Normalize();

                radiusVector = radiusVector.RotateAngleAxis(-rotSpeed*CurrentRotation.X, target->GetActorUpVector());
                radiusVector = radiusVector.RotateAngleAxis(rotSpeed*CurrentRotation.Y, CrossProd);
                SetActorLocation(target->GetActorLocation() + radiusVector);

                FRotator rot = (target->GetActorLocation() - GetActorLocation()).Rotation();
                GetController()->SetControlRotation(rot);


Logic of this code: getting the radius vector i. e. the vector starting at the viewed model and ending at my cam’s coordinates.

The rotation around the vertical axis is simple. But to rotate up and down we have to calculate an additional axis, which will be orthogonal to the plane constructed by Up-vector and radius-vector.

Then rotate the camera both in the Up-axis and the additional axis and set it looking at the model