🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

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

Started by
5 comments, last by Alberth 5 years, 2 months ago

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.

Advertisement

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.

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.

 

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.

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;
    }

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.

This topic is closed to new replies.

Advertisement