Move object around scene relative to the camera

Hey guys, I’ve been developing a small project in my spare time. Its an interactive solar system that is an almost 1:6 scale of ours. So it is still quite big. The structure of the solar system is quite simple it starts at a root object and parents and children reference each other. So If I move the root object all objects will move, If i select a child object with the mouse the object is brought to the camera and you can rotate around and zoom into the surface… This is how I utilize a floating origin point. Allowing for things like Shaders to function on all the planets and moons. It works great and is fast. However im having issues with controls and the scale to allow a user to navigate effectively.

What im currently trying to do is use the WASD keys to move the root object around the scene on the x, z axis (Forward, Back, Left and right if looking top down). That is working fine. However for navigation is cumbersome. As as soon as you rotate the camera the root objects movement reference is not updated and so If you rotate 45deg clockwise with the camera W is now Left. I’ve been trying to figure out how to keep WASD movement relative to the cameras view. So the A key will always move the root object to the left of the camera. W will always move up. But this should also take into consideration camera panning or ignore it. Im not sure how to go about it.

const moveSpeed = 1000000;
const keyMap: Record<string, boolean> = {
	w: false,
	a: false,
	s: false,
	d: false
};
const _camera = scene.activeCamera as BABYLON.ArcRotateCamera;
			const movement = new BABYLON.Vector3(0,0,0);
			const x = moveSpeed * Math.sin(rootObject.rotation.y);
			const z = moveSpeed * Math.cos(rootObject.rotation.y);

			if (keyMap['w']) {
				movement.x = x;
				movement.z = z;
			  }
			  if (keyMap['a']) {
				movement.x = -x;
				movement.z = -z;
			  }
			  if (keyMap['d']) {
                               // Ignore this.. was old method
				movement.x = -Math.sin(camera.rotation.y);
				movement.z = -Math.cos(camera.rotation.y);
			  }
			  if (keyMap['s']) {
                               // Ignore this.. was old method
				movement.x = -Math.cos(camera.rotation.y);
				movement.z = Math.sin(camera.rotation.y);
			  }

			movement.normalize();
			movement.scaleInPlace(scene.getEngine().getDeltaTime());
			rootObject.position.addInPlace(movement);

Key presses been listened by the actionManager. And from the _camera onwards is inside a registerBeforeRender

Edit 2… So close now. W and S are consistent. If the camera is above the sphere it will always go to the top and if you pan the camera level with the sphere it will always move away from the camera. S does the opposite.

Hello! I would do something like this: whenever a key is pressed, get the camera’s coordinate system, which consists of its forward, left and up vectors. Then, get the projection of these vectors in the ground plane (if you want the movement to stay on that plane). Then, apply the movement relative to these projected vectors (so, W/S move on the forward, and A/D move on the left vector). It would look something like this:

I hope this helps :slight_smile:

1 Like

I’ve almost got it correct here.

The plane/object should always rotate from a pivot point at origin. In this example its just a single plane. But see the plane a transformnode that has a mesh attached to it and other transformnodes at various other positions in the scene that parent to the plane. Basically if you select a mesh my code moves the mesh to 0,0,0 where the camera is located and when you rotate the root node it will look like the mesh at the origin is spinning. That code works fine.
The issue im still having is the orientation. “W” should always move the root node up the screen if the camera is positioned Top looking down and away from the camera if the camera is at the same height. It seems the camera.alpha might not be the best variable to use to do calculations as if you spin the camera fast then stop W and S controls seem to flip.

have a look at this if you haven’t already :slight_smile:

am on a similar pet project and have been using code (heavily) inspired from it and it works really well.

Im already using my own floating Origin code as my map size uses 64bit coordinates. The issue is navigating that space as the camera is fixed at origin and can only pan and rotate and so I still need to “move” around in the map space. This is so I can avoid clipping issues and still use Shaders.