Jump to content
  • Advertisement
_Zer0Sum_

Regarding rotation of objects away from origin (With 64-bit precision)

Recommended Posts

am having an issue with a short piece of code relating to rotation. 

Basically, I am trying to rotate an object (a planet, divided into chunks) about the origin (0,0,0). However, I am using a "floating origin" system which translates all objects in the world in the opposite direction to the players movement, to keep the player position at the origin (So, essentially, the world moves, not the player).

The below code works fine when the player is at the origin when the rotation is performed. But when the objects being rotated are moved from the origin (to simulate the player moving in the opposite direction) and the rotation is performed after the shift, the rotation is wrong.

I have tried changing the position of the centeroforbit object so that it remains fixed at 0,0,0, but this hasn't worked. 

I achieved some success by changing the centeroforbit position to the worldspace position of the player. This almost worked, but the rotation value wasn't quite correct.

I am using the Unity game engine, but any advice would be appreciated.


I know this is a long shot, and it's difficult to explain what exactly is happening here, but can anyone see any way to get the below code to work properly even when the position of the object being rotated changes, and moves from the origin?

The handle rotation code is inside an update loop, and it called continuously. 

This is the original code, this works fine only when the rotation is performed before the objects are moved:

Code (CSharp):
  1.  
  2.     private void HandleRotation()
  3.     {
  4.         PW_Vector3D rotatedPosition;
  5.         PW_Quaternion3D orbitRot = new PW_Quaternion3D(tDesc.rotationobject.transform.rotation);
  6.         PW_Vector3D ppos = body.GetComponent<PW_Planet>().planetposition;      
  7.         double orbitRadius = PW_Vector3D.Distance(ppos, tDesc.centreOfOrbit.GetComponent<PW_StaticObjectShifter>().position);
  8.  
  9.  
  10.  
  11.         rotatedPosition = orbitRot * (startingPosition + new PW_Vector3D(orbitRadius, 0, 0));
  12.         rotatedPosition +=  tDesc.centreOfOrbit.GetComponent<PW_StaticObjectShifter>().position;
  13.  
  14.         Quaternion q2 = Quaternion.Inverse(Quaternion.identity) * orbitRot.toQuaternion();
  15.         this.transform.position = rotatedPosition.toVector3f();
  16.         GetComponent<PW_StaticObjectShifter>().position = rotatedPosition;
  17.         this.transform.rotation = q2;
  18.     }
  19.  

This code *almost* works when the rotation occurs after shifting the objects, but the rotation is slightly off for some reason:
 

Code (CSharp):
  1.  
  2.     private void HandleRotation()
  3.     {
  4.         PW_Vector3D rotatedPosition;
  5.         PW_Quaternion3D orbitRot = new PW_Quaternion3D(tDesc.rotationobject.transform.rotation);
  6.         PW_Vector3D ppos = body.GetComponent<PW_Planet>().planetposition;      
  7.         PW_Vector3D v1 = mcs.shipworldspacepos;
  8.         double orbitRadius = PW_Vector3D.Distance(ppos,v1);
  9.  
  10.         rotatedPosition = orbitRot * (startingPosition + new PW_Vector3D(orbitRadius, 0, 0));
  11.         rotatedPosition += v1;
  12.  
  13.         Quaternion q2 = Quaternion.Inverse(Quaternion.identity) * orbitRot.toQuaternion();
  14.         this.transform.position = rotatedPosition.toVector3f();
  15.         GetComponent<PW_StaticObjectShifter>().position = rotatedPosition;
  16.         this.transform.rotation = q2;
  17.     }
  18.  

Thanks a lot for any advice that anyone can offer.

Share this post


Link to post
Share on other sites
Advertisement
Posted (edited)

I'm not going to try to read your broken code, because I don't know the libraries and conventions you are using, but I can tell you how to think about the situation so you can get it right yourself.

It doesn't matter whether the player rotates and moves around or the whole world rotates and moves around so the player stays at the origin. You are essentially describing the same reality using two different frames of reference (i.e., ways of assigning coordinates to points over time).

If you have a function that performs a rotation around the origin, you can easily wrap it around a couple of translations and turn it into a generic function that rotates around any point.

Point rotate_around_origin(Point p, Rotation r);

Point rotate_around_center(Point center, Point p, Rotation r) {
  return rotate_around_origin(p - center, r) + center;
}

 

If you get results that you don't expect, try to think of particular inputs to your functions and see if they get transformed the way you expect. You can do this following the code by hand or with the help of a debugger.

Edited by alvaro

Share this post


Link to post
Share on other sites

Thank you very much, I'll definitely try that approach today, and see how far I get.

I do know that you're right, this should be a matter of translating the rotation function, but I just can't get my head around what's happening.

I'll try your pseudocode, that might be what I'm missing.

 

Share this post


Link to post
Share on other sites

In short, rotation is always around the origin. Thus to rotate around another point, first translate that point to the origin, rotate, and then translate back.

Share this post


Link to post
Share on other sites

I have made some progress with this.

The below code performs a rotation about the origin, even when transform t is shifted away from it's initial position due to the floating origin system.

What happens is that the ship itself stays at the origin, but the world shifts, and the correct ship world space position updates. 

The below code does rotate the object (transform t) about the origin even after the world is shifted.

The only issues is that when the below function is called after the world shifts, the position of the object suddenly jumps and changes position. After that, it works ok. I suspect this must be something to do with "opos", which is the original position of the object before the world shifts.

Can anyone shed any light on what is going on here? It's close to working, it's just that jump in position that I am trying to fix.

 

    private void RotateAroundCustom(Transform t, PW_Vector3D opos)
    {
        PW_Vector3D pos = opos - mcs.shipworldspacepos;
        PW_Vector3D center =  new PW_Vector3D(0, 0, 0);
        
        PW_Vector3D dir = pos - center; // find current direction relative to center
        PW_Quaternion3D rot = new PW_Quaternion3D(mcs.rotationobject.rotation);

        dir = rot * dir;
        PW_Vector3D fpos = (center + dir);
      
        t.position = fpos.toVector3f();
        t.rotation = mcs.rotationobject.rotation;
      
        t.GetComponent<PW_StaticObjectShifter>().position = fpos;
        t.GetComponent<PW_Planet>().planetposition = fpos;
    }

Share this post


Link to post
Share on other sites

Set a breakpoint in the debugger that triggers with a move of the world, then step through this function line by line until you find the problem.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!