Overflight functionality

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Post Reply
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

Overflight functionality

Post by kubatp »

Hello,
I am looking for a simple implementation of a overflight (or flyover) functionality. Basically I want to use arrow keys to navigate camera (movement, yaw and maybe also pitch), ideally like the planes do (but like I said, roll is not necessary).
I can implement this on my own, but it doesnt make sense to reinvent a wheel and I am sure it can save some time not only for me but for other codes and it is also better to have something what is already nicely tweaked.
If there is similar thread, I am very sorry for duplication. I was trying the search function but nothing came up.
Thank you!
User avatar
saintnick
Halfling
Posts: 51
Joined: Tue Nov 27, 2018 1:41 am
x 5

Re: Overflight functionality

Post by saintnick »

Planes pitch up and down. To turn their wing "flaps" move up and down rolling the plane. For a mouse I translate this into pitch for up/down and roll for left/right. W can increase speed until engine is maxed out and S can reduce speed until a stall incurs. Yaw is unrealistic for a plane. So to turn right 90 degrees and continue straight in my flight simulator you move the mouse right and up (pitching and rolling you at the same time) until you have reached your target angle and then move the mouse left until you have rolled upright.

Without roll it sounds like you just want a flying first person flying camera. There are a lot of examples in the Ogre samples for this. WASD movement, mouse pitch/yaw and no ray keeping you pinned down to the ground. Shift is used to move faster. You can adapt the mouse input to keyboard as you said you wanted to use the arrow keys. Modify the keyReleased method to ignore letting go of WASD keys so you are always moving will give your plane a bit more realism than stopping in midair.
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

Re: Overflight functionality

Post by kubatp »

Hello saintnick,
thank you for your reply.

I took code from one of the samples (it is from MOGRE but I think easy to pick up for C++ developers as well). All is going fine, the only "issue" is that the camera is always going the way it is looking at. It means that if I want to look at terrain from top, I always go directly down. What would be the easiest way to modify this so I really overfly the terrain without going down? In summary - bird is always flying forward but looking down.

Code: Select all

private void FlyOverFrameRendering(FrameEvent evt)
{
	float moveScale = 3 * evt.timeSinceLastFrame;
	Degree rotateSpeed = 30;
	Degree rotScale = rotateSpeed * evt.timeSinceLastFrame;
	Mogre.Vector3 translateVector = Mogre.Vector3.ZERO;
	Degree scaleRotate = rotateSpeed * evt.timeSinceLastFrame;

	Mogre.Vector3 camVelocity = Mogre.Vector3.ZERO;
	keyboard.Capture();

	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_A))
	{
		translateVector.x = -moveScale;
	}

	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_D))
	{
		translateVector.x = moveScale;
	}

	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_W))
	{
		translateVector.z = -moveScale;
	}

	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_S))
	{
		translateVector.z = moveScale;
	}

	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_LEFT))
	{
		camera.Yaw(scaleRotate); 
	}

	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_RIGHT))
	{
		camera.Yaw(-scaleRotate);
	}

	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_UP))
	{
		camera.Pitch(scaleRotate);
	}

	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_DOWN))
	{
		camera.Pitch(-scaleRotate);
	}

	// toggle rendering mode
	if (keyboard.IsKeyDown(MOIS.KeyCode.KC_R))
	{
		if (camera.PolygonMode == PolygonMode.PM_POINTS)
		{
			camera.PolygonMode = PolygonMode.PM_SOLID;
		}
		else if (camera.PolygonMode == PolygonMode.PM_SOLID)
		{
			camera.PolygonMode = PolygonMode.PM_WIREFRAME;
		}
		else
		{
			camera.PolygonMode = PolygonMode.PM_POINTS;
		}
	}

	mouse.Capture();
	MOIS.MouseState_NativePtr mouseState = mouse.MouseState;

	if (!mouseState.ButtonDown(MOIS.MouseButtonID.MB_Left))
	{
		Degree cameraYaw = -mouseState.X.rel * .13f;
		Degree cameraPitch = -mouseState.Y.rel * .13f;

		camera.Yaw(cameraYaw);
		camera.Pitch(cameraPitch);
	}
	else
	{
		translateVector.x += mouseState.X.rel * 0.13f;
	}

	if (!translateVector.IsZeroLength)
	{
		// move the camera based on the accumulated movement vector
		camera.MoveRelative(translateVector);
	}
}
User avatar
saintnick
Halfling
Posts: 51
Joined: Tue Nov 27, 2018 1:41 am
x 5

Re: Overflight functionality

Post by saintnick »

Create a ray from the camera position to the terrain then check for an intersection. Then simply set the y position of the camera to the intersection plus however high you want to fly over.

Example: ( note the 5000 value for the y position of the ray. This should be higher than the highest point of your terrain to get an intersection.)

Code: Select all

			Ogre::Real OVERFLIGHT = 150;	// how far up you are flying
			Ogre::Real y = 5000;
			Ogre::Ray mRay(
				Ogre::Vector3(mCameraNode->getPosition().x, y, mCameraNode->getPosition().z),
				Ogre::Vector3::NEGATIVE_UNIT_Y);
			Ogre::Vector3 intersection;
			Ogre::Real scale = mVolumeRoot->getChunkParameters()->scale;
			bool intersects = mVolumeRoot->getChunkParameters()->src->getFirstRayIntersection(mRay, intersection, scale);
			if (intersects)
			{
				intersection *= scale; // As it is in volume space.
				Vector3 newCamPosition = mCameraNode->getPosition();
				newCamPosition.y = intersection.y + OVERFLIGHT;
				mCameraNode->setPosition(newCamPosition);
			}
			{
This example uses the volume component for terrains. mVolumeRoot is the terrain volume. After casting the ray you check if intersects is true, if so you set the position of the camera node to itself plus your overflight variable.

You can also add keyboard input for - and + to change OVERFLIGHT variable so you can change the height of which you stay above the terrain.

Keep in mind that this isn't a natural behavior. Planes and birds don't fly higher or lower when the terrain directly below them is a small hill or dip.
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

Re: Overflight functionality

Post by kubatp »

Thank you for your reply saintnick.
I will definitely try that and reply how it went, I was just dragged into something else temporarily. I should come back to this soon.
kubatp
Gnome
Posts: 368
Joined: Tue Jan 06, 2009 1:12 pm
x 43

Re: Overflight functionality

Post by kubatp »

I was trying to make a progress in this but the technique you are suggesting is not what I am trying to achieve.

The best approach would be this:
It would work exactly the same as the code I posted before but once user presses left, right, up or down keys, it will not only yaw or pitch the camera but it will also store this change to an external variable. Once player presses WASD keys again, it will move the camera in the specific direction but it will also use the stored variable to calculate the difference between current camera direction and the "movement" direction.

An example:
Let's say we have a flat terrain (plain) and I set the initial movement direction by mouse to be parallel to terrain (aka I am looking horizontally). When I press W now, it moves further parallely to terrain. When I press "arrow down" key, it pitches the camera and saves to variable how much it pitched the camera. Let's say I will pitch it 90 degrees (aka I am now looking direction to terrain below the camera). Now I press W again - I am still moving the camera horizontally (parallely to terrain) but already looking to the terrain below.

I am sure this is not that difficult, but can someone help me to understand how to save this "pitch" and "yaw" changes and apply them later?
Thank you!
User avatar
saintnick
Halfling
Posts: 51
Joined: Tue Nov 27, 2018 1:41 am
x 5

Re: Overflight functionality

Post by saintnick »

Storing last camera pitch and yaw from mouse:

Code: Select all

lastCameraPitch = cameraPitch;
lastCameraYaw = cameraYaw;
Storing last camera rotations with keyboard:

You are using a speed times frames per second to rotate your camera. I don't understand how to store these changes. However I am asking my self why you want these changes in the first place.
Once player presses WASD keys again, it will move the camera in the specific direction but it will also use the stored variable to calculate the difference between current camera direction and the "movement" direction.
Then I re-read this:
What would be the easiest way to modify this so I really overfly the terrain without going down? In summary - bird is always flying forward but looking down.
I missed this earlier.

So instead of translating your camera with respect to orientation you would translate it only considering movement direction. This will achieve a bird flying straight and looking down. (or where ever you rotate the camera to look)

You get the separation of movement direction and orientation by using scene nodes.

Code: Select all

Ogre::SceneNode *mCameraNode = mScnMgr->getRootSceneNode()->createChildSceneNode();
Ogre::SceneNode *mCameraMoveNode = mCameraNode->createChildSceneNode();
mCameraMoveNode->attachObject(mCamera);
Apply your rotations to mCameraNode. Apply your translateVector to mCameraMoveNode. I have not tested this but it should work.

edit:
I had it in reverse.

Code: Select all


//  in setup
Ogre::SceneNode *mCameraNode = mScnMgr->getRootSceneNode()->createChildSceneNode();
Ogre::SceneNode *mCameraRotationNode = mCameraNode->createChildSceneNode();
mCameraRotationNode->attachObject(mCamera);

// every frame update
mCameraRotationNode->pitch(cameraPitch);
mCameraRotationNode->yaw(cameraYaw);
mCameraNode->translate(translateVector);
Post Reply