Moving Frame of Reference

Hi,

I am creating a few prototypes at the moment and I got stuck on the last one.
I am trying to allow a player to change his frame of reference from the world coordinate system to a moving one, like a vehicle.

So when a player moves around the world normally and then moves into, let’s say a planes cargobay, his movements should now be relative to the vehicle instead of the world.

Just to clarify, I am not talking about steering a vehicle, I want to walk around a moving vehicle without falling off. In theory I just need to change the players reference coordinate system from world to an actors local one. But that seems to be rather hard in practice.

Here I have an image to illustrate the problem a bit

Is there an easy way to do this in unreals framework, or do I have to rewrite a few things in engine code?

What I’ve tried so far:

  • adding velocity changes from the frame to all its children (so if the plane changes its velocity, we just add that to the players velocity and he stays in place, but that does not work for rotations[rotations could work with transformations, but that is also kinda hacky to do that on a top level of abstraction])
  • Attaching the player to a vehicles root, which did’t work at all, and all sorts of bad things happend
  • Attach the player to a NOT root component of the vehicle blueprint and then pass all the movement inputs to this component to move it relative to the vehicle. (really hacky way of doing it, since you lose your movementComponents functionality )

Things that could work, but I didn’t try yet, because they all seem hacky:

  • build the whole thing in actor space (e.g inside a Blueprint with components moving around)

Thanks in advance.

I unfortunately don’t have anything to add as far as a real suggestion or solution, but I thought I’d chime in since I’ve been working on a prototype to demo pretty much the same thing (but failing miserably). My approach has been a bit different, in that I’ve been trying to model multiple frames of reference as a hierarchy of PhysX scenes. I’m trying to do it this way primarily since I want to ensure PhysX dynamics go to sleep if they are stable within their local frame of reference. It would also allow me to do some really cool stuff with scene-wide forces.

I have an example world in my head that fleshes out similar to your diagram. Consider the following initial physics scene/frame of reference hierarchy:



Space
 +-Planet
 |   +-Space ship
 +-Space station


The space scene is by definition (since it’s the root scene) static, covers the entire global coordinate extent and in this case would have no scene-wide forces. For simplicity, the planet scene is stationary within space and centered on a sphere, with a scene-wide radial gravity that applies an acceleration toward’s it’s local origin to all child actors and scenes within its bounds. The space ship scene includes the interior of a space ship and, while not moving locally, on its own has no scene-wide force. Finally, the space station scene is a rotating ring with artificial gravity created by centripetal force (think the movie Elysium). Again for simplicity, the center of the space station scene can be considered stationary within space.

The way I envision this working in real time is that initially everything in the world is sleeping physics-wise. The space ship scene is stationary on the surface of the planet. There is a character sitting in the space ship experiencing that scene’s forces, which is the accumulation of forces inherited down from the root, including those related to the forces each scene experiences within it’s parent frame of reference. At this point, that means the character experiences only gravity. The space ship takes off and begins to fly away, which changes the scene-wide force experienced by the character, since now it includes gravity plus the opposite of the acceleration vector of the space ship within the planet scene.

Eventually, the space ship passes out of the bounds of the planet scene, at which point it transitions into the root space scene. As it flies through space toward the space station, the scene-wide force experienced within the space ship scene is only that related to the space ship’s acceleration within the root frame of reference. When the space ship approaches the space station, it transitions into the space station scene. Since the space station scene is rotating, the space ship’s local velocity and acceleration change to offset the new scene-wide forces that apply to it. As the space ship flies in a way to match the rotation of the “surface” (inner side facing the center) of the space station, the local velocity and acceleration of the space ship approach zero. Eventually it is stationary within the space station scene, as it lands on the surface. The character in the space ship is now experiencing the centripetal force inherited by the space ship scene. The character leaves the space ship, transitioning into the space station scene. Since the space ship scene was stationary/asleep within the space station scene, the character’s local velocity and acceleration are unchanged. The character then throws a ball up in the air, which rises and falls based on the scene-wide centripetal force applying to the space station scene. The ball comes to rest and goes to sleep, despite it’s constantly changing global velocity and acceleration.

I know this sounds extremely ambitious, but I think the hard part is really modifying the existing physics “middleware” in the engine, as opposed to the from-scratch coding that’s needed to implement this on top of PhysX. With some simplifying assumptions regarding how to deal with actors and movable child scenes that cross over scene boundaries, each scene within the hierarchy could really be considered independently. Since this would allow the greatest opportunity for dynamics to fall to sleep, hypothetically this means it could be more efficient (not to mention the actor partitioning should reduce the number of overlap tests needed).

All that said, my problem has been that the use of a single PhysX scene (setting aside the async and cloth scenes) is highly embedded in the core of the engine code. So far it’s been a frustrating/confusing attempt. All I’ve managed to do is stick with a single scene with a sphere that applies radial gravity to a handful of cubes that start off floating above it’s surface. They all fall to the surface and eventually fall to sleep (I had to bypass FPhysScene::AddForce and directly call physx::PxRigidDynamic::addForce to do that). Then I can “hit” the sphere in a direction, which causes the cubes to dislocate but follow the sphere, with it all eventually falling to sleep again.

I’m pretty stuck trying to introduce the PhysX scene hierarchy I need. And at this point I think I’m going to step back and implement a prototype directly on top of PhysX. Then, once I have that working, I’ll reattempt reworking the core engine code to handle a hierarchy of scenes.

I also welcome any comments (even if telling me to stop wasting my time on this) and/or references to any similar prior notes or work. I’ll let you know if I make any progress on the above or with one of the methods you mention.

Sorry for the long post. (I cut myself off from going into details on the cool stuff that this would hypothetically allow me to do, like having a meteor hit the space station, with it’s resulting motion applied down into it’s interior scene…)

I am probably over simplifying this but…

Can you not get the rotation and location of the actor you want to stick to and also its dimensions, feed them into your player and when the player moves around on that ship, apply his offset to the rotation and location matrix of the moving actor. When your player goes out of bounds of the dimensions of the ship, then just block movement…

The outcome is that, your actor will move, and your player will move too (due to adding the actors rotation and location to your players matrix), then any offset will allow your player to move freely around the ship… and finally, to stop him falling off, you have the dimensions of the ship limiting the movement.


        // pseudo code
	for (...)
	{
            // If correct actor
              FVector actorLocation = GetActorLocation();
              FRotator actorRotation = GetActorRotation();

            // If player
              FVector playerLocation = GetActorLocation();
              FRotator playerRotation = GetActorRotation();

            // If player is not out of actor bounds : https://answers.unrealengine.com/questions/41596/how-to-get-the-size-of-a-static-mesh.html
              SetActorLocation( actorLocation * playerLocation ); // I don't know if multiplying these vectors will work, I don't know if they are operator overloaded <shrugs> I assume they are.
              SetActorRotation( actorRotation * playerRotation );
	}

I don’t know enough about the functions, but I assume it’s something like this… I’ve probably totally misunderstood your question… but… whatever. :slight_smile:

jimmyt1988, that would certainly work for a simple level, but where I think that would get very messy and inefficient is if you have a lot of physics-simulated actors. In that case, you want to give those actors every opportunity to fall asleep to keep performance acceptable. If all of those actors were constantly being moved and rotated around in the physics scene, they would almost certainly never fall asleep. I also think you want to avoid frequently applying discrete location and velocity changes directly to a physics-simulated actor, otherwise you can expect odd behavior. By simulating the physics of those actors within their local frame of reference I would expect good simulation results and performance.

Then I have learnt something new :slight_smile: Thanks brah!

*edit: missed three posts before me :stuck_out_tongue:

@kostrowski

Hey, your problem is indeed pretty similar, if not exactly the same.

I also wanted to create a space game that allows you to move into different frames of reference with their own gravity fields. Actually it started by watching the series Firefly. I wanted to make a little game where you live in your ship, walk around on it and then seemlessly leave it to go to space or another space station with a different gravity vector or no gravity at all.
But I really did not want to have a heavy gravity simulation, I’d much rather explain stuff simply with Scifi^^ and keep it simple.

Anyways, since this is a ridiculously ambitious project, I broke it down into modules and before that even in themed prototypes that don’t really have to do with the game at all. So I created little physics games, lunar landers, orbit stuff, multiple point gravity simulations, EVA suit physics and stuff like that, and that worked pretty well, I kinda had an output of 1 prototype per day with no problems at all - until yesterday.

For some reason, the current implementation of actors and physics makes it kinda hard to change the frame of reference for an actor.

But anyways, after thinking about it today, I came to the conclusion that the first point I tried is the easiest one [I mean just setting the frame of reference per code and then do the velocity/rotation transformation math per frame. All actors stay in the world frame of reference]. That is what the CharacterMovementComponent does as well when you step on movable objects → that allows me to stay inside of unreals framework without changing too much.
I don’t really want to rewrite all the network and physics stuff at this point. The only thing I have to change is the way gravity works inside of actors. I gotta change it from a number + fixed vector to a variable vector and that should be it.
But then again, it’s not the best way of doing it, still is pretty hacky and not very clean.

This way I probably have to use Reference Frame priorities to handle multiple stacks of them. Lets say a player is inside of his ship and the ship flies into a hangar. You’d want the player to stay relative to the ship and not switch to hangars transform until he leaves his ship. Hacky as ****, but you gotta fake it if you can’t do it properly, don’t you? :smiley:

But at first, I gotta try it out, still not sure if this will work properly for rotations. Rotating the frame of reference means you kinda have to rotate all it’s children relative to it’s origin. I’d much rather have a proper scene setup do this for me…

@jimmyt1988
Yeah, that is the hacky approach I used first, but its still not a proper setup. You actually posted while I was writing mine, and I guess that this is the easiest implementation but again, it’s not very clean.
I’d much rather have a proper scene setup, so the built in scene graph transformation matrices can handle stuff for me.

Hey, I justed wanted to give you guys a quick update.

I pretty much solved it. I wrote my own MovementComponent and Pawn classes that can handle any gravity vector and transition between different ones.
I solved the reference frame issue simply by adding velocities to my pawn. So if the frame moves, I add the velocity to the pawn. If the reference frame rotates, I simply calculate the tangential velocity aswell. I took most of that from the CharacterMovementComponent and incorporated threedimensional gravity alignment of my pawn.
That works pretty well, but I still have a lot of work to do to get the movement on par with the CharacterMovementComponent, since I just wrote the bare bone for the movement. It is still jittery on walls and slopes.