Announcement

Collapse
No announcement yet.

How do quats work?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    How do quats work?

    Hi, I am currently changing my FRotator based flight simulator to a Quat based system due to many problems I encountered .

    I don't have much experience in working with quats and I am getting the same errors with quats with the ones I encountered with FRotators.

    I want to change the Yaw and Pitch of an actor at the same time without changing the Pitch. In FRotators, when a Yaw and Roll value is added to an actor, a value of pitch is also added to it automatically. I don't want that to happen.

    But the same thing is also happening with quats.

    Here is my code
    Code:
    FRotator NewRot = FRotator(Rotation2D.X, Rotation2D.Y, Rotation2D.Y*0.5);
    		FQuat NewQuat(NewRot);
    		FRotator CurrentRot = GetActorRotation();
    		FQuat CurrentQuat(CurrentRot);
    		CurrentQuat = CurrentQuat * NewQuat;
    		//CurrentQuat.Normalize();
    		SetActorRotation(CurrentQuat.Rotator());
    Also I want to know if this is the best method to do Quat based calculations?

    #2
    Can you state your overall goal not just the code? why did you make a rotator out of a rotator2D with 0.5 for the y for z ?

    Rama
    UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

    ♥ Rama

    Comment


      #3
      Originally posted by Rama View Post
      Can you state your overall goal not just the code? why did you make a rotator out of a rotator2D with 0.5 for the y for z ?

      Rama
      Well X and Y are the player inputs stored in a 2d vector. Then every tick after some calculations, they are used to control the direction of the aircraft. Y is for the Yaw and X is for the pitch. I want when the aircraft rotates in the yaw directions, there is a bit of roll to it. Like it tilts a bit to the sides.(without changing the pitch)

      How ever by this method, the pitch of the aircraft changes if both yaw and roll are changed at the same time.

      Comment


        #4
        You probably don't want to modify your quat with Yaw, Pitch, and Roll at all. I'm pretty sure those are just abstractions to make quats easier to work with, but it introduces the exact same problem by having it still act like an FRotator.

        You actually want to transform the quat itself. You store your ship's orientaiton as a quat. And then when you have roll, pitch, yaw inputs, you transform the quat around the appropriate axes.

        I've done this before with the GLM library, but the principle is the same.

        So for roll, for example, this may work in Unreal:

        MyQuat *= FQuat(FRotator(0.f, 0.f, RollAmount));

        I'm creating a Quat from a rotator, and transforming my current ship's quat by the quat that gives roll. And you do the same for pitch and yaw.



        Actually I just double checked your code again and it looks like you're basically doing just that. Maybe there are ways to optimize it a little by not converting between rotators and quats so much.

        The thing is though, you say your yaw and roll change at the same time, and that seems about right. FRotator(Rotation2D.X, Rotation2D.Y, Rotation2D.Y*0.5);

        The yaw and roll are both derived from the same value here. I'm not entirely sure why you're trying to get roll from rotation2D.y*.5 but that may be why it's happening. In fact, if the game is 3D, why have a Rotation2D of some sort at all.
        Last edited by illYay; 10-26-2014, 04:37 PM.

        Comment


          #5
          I decreased the amount of conversion to something like this

          Code:
          		FRotator NewRot = FRotator(Rotation2D.X, Rotation2D.Y, 0);
          		FQuat NewQuat(NewRot);
          		FQuat CurrentQuat = GetActorQuat();
          		CurrentQuat = CurrentQuat * NewQuat;
          		SetActorRotation(CurrentQuat.Rotator());
          I am using a FVector2D to store the player input of directions. X for top or bottom and Y for left and right.

          What I am trying to achieve is, when the Yaw changes, i.e. the Y axis, there is a bit of roll to the spaceship. Like the space ship slightly twists in that direction. So
          Code:
          Rotation2D.Y*0.5
          is used as a roll value. This works but there is a side effect.

          When the Roll and Yaw changes, the pitch values goes down without any reason.

          The same problem also happens in the flying template. If you move towards a side, your spaceship goes towards the ground.

          Comment


            #6
            I've posted a few options below, let us know what each ones does for you


            If you are using Character then you can replace GetRootComponent() with Mesh

            Code:
            //inside actor class you want to rotate
            
            USceneComponent* RootComp = GetRootComponent();
            if(!RootComp) 
            {
              //this should probably !ever happen
               return;
            }
            
            
            //Get!
            FVector CompWorldLocation = RootComp->GetComponentLocation(); 
            FQuat CompQuatRotation = RootComp->GetComponentQuat();
            
            
            //non interp case
            CompQuatRotation = FRotator(Rotation2D.X, Rotation2D.Y, Rotation2D.Y*0.5).Quaternion();
            
            //Set!
            RootComp->SetWorldLocationAndRotation(CompWorldLocation,CompQuatRotation);

            Just a note, I've not had any issues with converting a Quaternion to Rotator and back again, the main issue is actually where and how the new rotation is applied to the AActor.

            So I am using USceneComponent::SetWorldLocationAndRotation as a test to see if that helps you.

            Let me know how it goes!

            ~~~

            Interpolation

            Personally I recommend interpolating instead of just setting

            This assumes you are running the code every tick

            Code:
            USceneComponent* RootComp = GetRootComponent();
            if(!RootComp) 
            {
              //this should probably not ever happen
               return;
            }
            
            
            //Get!
            FVector CompWorldLocation = RootComp->GetComponentLocation(); 
            FQuat CompQuatRotation = RootComp->GetComponentQuat();
            
            //Interpolate here if running every tick, using between above rotation and your new rotation
            CompQuatRotation = 
               FQuat::Slerp(
                  CompQuatRotation,
                  FRotator(Rotation2D.X, Rotation2D.Y, Rotation2D.Y*0.5).Quaternion(),
                  0.03 //Interp Speed
            );
            
            //Set!
            RootComp->SetWorldLocationAndRotation(CompWorldLocation,CompQuatRotation);

            ~~~

            Alternative

            You can also try this:

            Code:
            FTransform Trans = GetTransform();
            Trans.SetRotation(FRotator(Rotation2D.X, Rotation2D.Y, Rotation2D.Y*0.5).Quaternion());
            SetActorTransform(Trans);




            Rama
            Last edited by Rama; 10-26-2014, 05:29 PM.
            UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

            ♥ Rama

            Comment


              #7
              Thanks for the reply Rama but sadly I am getting the same error with all method except SLerp. I have not tried SLerp yet it needs me to rewrite the whole system. But I think i will still get the same problem. Because the problem sadly happens when quats are multiplied. A pitch is introduced in it automatically.

              Here is my code
              Code:
              		GEngine->AddOnScreenDebugMessage(-1, DeltaSeconds, FColor::Blue, "Raw Values =>  Pitch = " + FString::SanitizeFloat(Rotation2D.X) + " Roll = " + FString::SanitizeFloat(Rotation2D.Y) + " Yaw = " + FString::SanitizeFloat(Rotation2D.Y));
              		FRotator NewRot = FRotator(Rotation2D.X, Rotation2D.Y, Rotation2D.Y);
              		FQuat NewQuat(NewRot);
              		GEngine->AddOnScreenDebugMessage(-1, DeltaSeconds, FColor::Cyan, "Change in FRotator =>  Pitch = "+ FString::SanitizeFloat(NewRot.Pitch) + " Roll = " + FString::SanitizeFloat(NewRot.Roll) + " Yaw = " + FString::SanitizeFloat(NewRot.Yaw));
              		FQuat CurrentQuat = GetActorQuat();
              		GEngine->AddOnScreenDebugMessage(-1, DeltaSeconds, FColor::Green, "Current FRotator =>  Pitch = " + FString::SanitizeFloat(CurrentQuat.Rotator().Pitch) + " Roll = " + FString::SanitizeFloat(CurrentQuat.Rotator().Roll) + " Yaw = " + FString::SanitizeFloat(CurrentQuat.Rotator().Yaw));
              		CurrentQuat = CurrentQuat * NewQuat;
              		GEngine->AddOnScreenDebugMessage(-1, DeltaSeconds, FColor::Yellow, "After Adding =>  Pitch = " + FString::SanitizeFloat(CurrentQuat.Rotator().Pitch) + " Roll = " + FString::SanitizeFloat(CurrentQuat.Rotator().Roll) + " Yaw = " + FString::SanitizeFloat(CurrentQuat.Rotator().Yaw));
              		SetActorRotation(CurrentQuat.Rotator());
              I have attached 2 images of how the values are changing I think after adding. So the problem is not with applying the rotators. I think it is with how quats are added. I need to ignore the FRotator Pitch component of the added quats, Guess that should solve the problem.
              Attached Files

              Comment


                #8
                Revision of My Earlier Statement

                You know, I just checked my code base for one of my paid projects were I developed replicating 6DOF movement of a space ship.

                This is a multiplayer game where the ship can move in literally any angle and can roll and everything!

                And I am using just this which I posted on the UE4 wiki:

                Code:
                FORCEINLINE void AddToActorRotation(const FRotator& Rot)
                {
                	FTransform Trans = GetTransform();
                	Trans.ConcatenateRotation(Rot.Quaternion());
                	SetActorRotation(Trans.Rotator());
                }
                The user can roll and do pitch and yaw adjustments all at the same time!


                You might want to check your whole system and start over because I can now verify full 6DOF including rolling using just my above code, in a multiplayer context!

                The ship unit in this game I am describing is a Character.

                Good luck!

                Rama
                Last edited by Rama; 10-27-2014, 08:42 PM.
                UE4 Marketplace: Melee Weapon Plugin & Compressed Binary Save System Plugin | Rama's C++ AI Jumping Videos | Vertex Snap Editor Plugin

                ♥ Rama

                Comment


                  #9
                  Originally posted by Rama View Post
                  If you are using Character then you can replace GetRootComponent() with Mesh
                  <snip>
                  Rama
                  I've been working on my own version of a multiplayer 6DOF pawn. I have been working on the assumption that I should use APawn with UFloatingPawnMovement (and INetworkPredictionInterface for networking), but I really don't want to get this deep into the low-level networking code for multiplayer movement (why reinvent the wheel when there are far superior solutions already coded). I just stumbled on this thread in my research and wondered if you could share a bit about how to turn ACharacter into a starship? You suggest replacing GetRootComponent with Mesh, but Mesh in Acharacter is a USkeletalMeshComponent... I feel like I'm missing a piece of information.

                  Comment


                    #10
                    Kind of like magnets

                    Don't worry about "how" they work, you'd need at least a Bachelros in mathematics, just worry about WHAT they can do, how they are used, and when to use them.
                    Last edited by User-658380556; 11-20-2014, 03:53 AM.

                    Comment

                    Working...
                    X