Free Flight (space flight) functions

A forum to store posts deemed exceptionally wise and useful
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Free Flight (space flight) functions

Post by arras »

Since there are many people contacting me, I decided to make thread in this room to show some useful functions which solwe some particular problems when simulating free flight in 3D using Irrlicht.

Happy coding :)

[edit 17.02.2007]
code below was updated and should work with Irrlicht 1.2 now.

You may also look at example code (small demo) on second page of this post.
Last edited by arras on Sat Feb 17, 2007 7:15 pm, edited 3 times in total.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Cockpit camera:

Code: Select all

//--- set camera to behave as cockpit camera of ship ---
void makeCockpit(irr::scene::ICameraSceneNode *camera, //camera
                irr::scene::ISceneNode *node, //scene node (ship)
                irr::core::vector3df offset) //relative position of camera to node (ship)
{
    // get transformation matrix of node
    irr::core::matrix4 m;
    m.setRotationDegrees(node->getRotation());

    // transform forward vector of camera
    irr::core::vector3df frv = irr::core::vector3df (0.0f, 0.0f, 1.0f);
    m.transformVect(frv);
    
    // transform upvector of camera
    irr::core::vector3df upv = irr::core::vector3df (0.0f, 1.0f, 0.0f);
    m.transformVect(upv);

    // transform camera offset (thanks to Zeuss for finding it was missing)
    m.transformVect(offset);

    // set camera
    camera->setPosition(node->getPosition() + offset); //position camera in front of the ship
    camera->setUpVector(upv); //set up vector of camera
    camera->setTarget(node->getPosition() + frv); //set target of camera (look at point) (thx Zeuss for correcting it)

    // update absolute position
    camera->updateAbsolutePosition();
}
Last edited by arras on Sat Feb 17, 2007 6:45 pm, edited 6 times in total.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Turn, pitch, roll:

Code: Select all

//--- rotate node relative to its current rotation -used in turn,pitch,roll ---
void rotate(irr::scene::ISceneNode *node, irr::core::vector3df rot)
{
    irr::core::matrix4 m;
    m.setRotationDegrees(node->getRotation());
    irr::core::matrix4 n;
    n.setRotationDegrees(rot);
    m *= n;
    node->setRotation( m.getRotationDegrees() );
    node->updateAbsolutePosition();
}

//--- turn ship left or right ---
void turn(irr::scene::ISceneNode *node, irr::f32 rot)
{
    rotate(node, irr::core::vector3df(0.0f, rot, 0.0f) );
}

//--- pitch ship up or down ---
void pitch(irr::scene::ISceneNode *node, irr::f32 rot)
{
    rotate(node, irr::core::vector3df(rot, 0.0f, 0.0f) );
}

//--- roll ship left or right ---
void roll(irr::scene::ISceneNode *node, irr::f32 rot)
{
    rotate(node, irr::core::vector3df(0.0f, 0.0f, rot) );
}
Last edited by arras on Sat Feb 17, 2007 6:47 pm, edited 2 times in total.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Move ship in space:

Code: Select all

//--- move ship acording to its rotation ---
void move(irr::scene::ISceneNode *node, //node to move
            irr::core::vector3df vel) //velocity vector
            // for example to move node 10 units forward use vector3df(0,0,10)
{
    irr::core::matrix4 m;
    m.setRotationDegrees(node->getRotation());
    m.transformVect(vel);
    node->setPosition(node->getPosition() + vel);
    node->updateAbsolutePosition();
}
Last edited by arras on Sat Feb 17, 2007 6:50 pm, edited 1 time in total.
Zeuss
Posts: 114
Joined: Mon Nov 08, 2004 9:02 pm
Location: Canberra - Australia
Contact:

Post by Zeuss »

thanks a lot arras, to anyone else who is going to use it, the makecockpit function also act's are update, else without it just the ship rotates, and not the camera.

I've wrapped it up in a class, for use in my game. If anyone wants the class, just ask.

Arras i've encountered a few problems. 1st the offset doesnt work correctly. because it doesnt get transformed. But even when i do transform it and then add it, it still does not get the camera in the right place. And the movement seems to seperate the camera from the ship instantly. Maybe its the way i have it in the class, but i dont think so. ill keep working in it for the moment.
Help make Irrlicht even Better! Create and submit your own Irrlicht Extension
Want a Games Education? Try The Academy of Interactive Entertainment
Zeuss
Posts: 114
Joined: Mon Nov 08, 2004 9:02 pm
Location: Canberra - Australia
Contact:

Post by Zeuss »

ok ive fixed the camera offset. But the move function is proving a real problem. the camera and the node just seem to seperate (happens pretty fast). And i end up seeing the lovely standard grey. Instead of my skybox or anything else.
This happens no matter what value in the vector3df i pass into the move function.

Anyway its late now, tommorrow ill just add a simple gui to spit out the coord's and try and see what is happening.
Help make Irrlicht even Better! Create and submit your own Irrlicht Extension
Want a Games Education? Try The Academy of Interactive Entertainment
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Zeuss >> thanks for finding that problem with camera offset. I corected that in snipet.

about that movement and camera separation, it should work corectly, just make sure you update node as well as camera position each loop. Also make sure that you update node firsth then camera.

You can aslo try to make node to be parent scene node of camera, that way Irrlicht handle offset and position on its own, you just need to care about rotation.

I dont have much time now to test it so let me know if there are still problems and if you were able to solve that camera-movement issue.
Zeuss
Posts: 114
Joined: Mon Nov 08, 2004 9:02 pm
Location: Canberra - Australia
Contact:

Post by Zeuss »

ok all bug fixed. First off getRelativeTransformation also gets the displace to 0,0,0 as well as the rotation, so was causing faults.
Also when setting the new cameras position, the target wasnt getting updated to the ship node, well not for me anyway. So here's the fixed code:


Move Ship in space

Code: Select all


 //--- move ship acording to its rotation ---
void move(irr::scene::ISceneNode *node, //node to move
            irr::core::vector3df vel) //velocity vector
            // for example to move node 10 units forward use vector3df(0,0,10)
{
    //Zeuss - Has to be getRotation and not getRelativeTransformation
    irr::core::matrix4 m;
    m.setRotationDegrees(node->getRotation());
    m.transformVect(vel);
    node->setPosition(node->getPosition() + vel);
}


Cockpit View

Code: Select all

 //--- set camera to behave as cockpit camera of ship ---
void makeCockpit(irr::scene::ICameraSceneNode *camera, //camera
                irr::scene::ISceneNode *node, //scene node (ship)
                irr::core::vector3df offset) //relative position of camera to node (ship)
{
    //get rotation matrix of node - Zeuss must be getRotation not getRelativeTransformation
	irr::core::matrix4 m;
	m.setRotationDegrees(m_node->getRotation());
   
    // transform forward vector of camera
    irr::core::vector3df frv = irr::core::vector3df (0.0f, 0.0f, 1.0f);
    m.transformVect(frv);
   
    // transform upvector of camera
    irr::core::vector3df upv = irr::core::vector3df (0.0f, 1.0f, 0.0f);
    m.transformVect(upv);

    // transform camera offset (thanks to Zeuss for finding it was missing)
    m.transformVect(offset);
   
    // set camera
    camera->setPosition(node->getPosition() + offset); //position camera in front of the ship
    camera->setUpVector(upv); //set up vector of camera >> Zeuss - tested with +node->getPostion() and it didnt work, but this works fine.
    camera->setTarget(node->getPosition() + frv); //set target of camera (look at point) >> Zeuss - Dont forget to add the node positiob
} 
Now it works for fine for me. Thanks so much for your help arras. A demo of what im working on well be out soon.
Help make Irrlicht even Better! Create and submit your own Irrlicht Extension
Want a Games Education? Try The Academy of Interactive Entertainment
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

Zeuss >> I am sorry for that camera issue, of course you are right about that target vector. Its becouse I have all those functions build in classes and was just rewriting them without testing (not enought time). Also my camera was child of node so I did not update those vectors with node position, since they were relative.

That getRelativeTransformation function should work on the other hand, at last its working for me in some other casses when transforming vectors. On the other hand there is nothing wrong building matrix from rotation. I just tought it may be a little bit faster to get matrix directly from node.

Thanks for debugging that code :wink:
Zeuss
Posts: 114
Joined: Mon Nov 08, 2004 9:02 pm
Location: Canberra - Australia
Contact:

Post by Zeuss »

it was a pleasure, the bugged code help me understand how Irrlicht deals with rotations and stuff. Thanks alot.
Help make Irrlicht even Better! Create and submit your own Irrlicht Extension
Want a Games Education? Try The Academy of Interactive Entertainment
bwegge

Direction of flight

Post by bwegge »

I am total newbie to IrrLicht and still struggling with alot of basic issues .. like camera movement. Since I am trying to make a simple spaceship game, the code and explanation in this thread was very helpful.

However, I think I am missing something. As I see it one the things you really want in your spaceship game is the direction you are looking (for firing missiles, guns and so on). How does this fit into code above?
Can it be found using the parent node of the camera, or the camera node itself?
Zeuss
Posts: 114
Joined: Mon Nov 08, 2004 9:02 pm
Location: Canberra - Australia
Contact:

Post by Zeuss »

the direction the camera is looking, is set by setting a target point e.g. (0,0,10)
This is great for tracking stuff as you can just put in its position, but makes spaceship cam a bit more trickey.

But as we are rotating the ship (the node) as well as the changing the postion and target for the camera you can get the current rotation of the ship with the following line

node->getRotation();

This returns the relative rotations of the ship.
It returns it as a vector3df. In the form (pitch,turn,roll). I believe it is in degrees but i am not entirely sure.
Help make Irrlicht even Better! Create and submit your own Irrlicht Extension
Want a Games Education? Try The Academy of Interactive Entertainment
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

In the form (pitch,turn,roll)
well actualy it is not. Rotation you get is in Euler angles, called afther one mathematican. Try to search internet about it, since its quit inportant, that you understand hove they work.

Basicly you rotate object around its axis one by one. Once you rotate object aroun Z axis for example, you rotate X and Y axis as well. Thats why order of rotation is inportant. Irrilch seems to rotate in Z-Y-X order. Thats reason why you need functions for turn, pitch, roll.

bwegge >> direction you are looking is stored in node rotation. From that you can get forward vector (direction you are looking) like this:

Code: Select all

irr::core::vector3df vector = irr::core::vector3df(0,0,1);
irr::core::matrix4 m;
m.setRotationDegrees(node->getRotation());
m.transformVect(vector);
where vector is your relative (relative to object rotation) normalized forward vector. Afther you transform it, you get absolute forward vector (absolute mean in world coordinate system) This code is used in movement function -moves your node in direction if faces.
Guest

Post by Guest »

I see. It seems alot easier than the approach I was considering. My initial thoughts where to use the normal of far_plane in camera frustrum, but your (arras) method seems more sensible.

Thanks for the help :o)
Fingers
Posts: 38
Joined: Thu Feb 10, 2005 10:17 am
Location: South Africa

Post by Fingers »

Hi all,

and Yes I Know this is a old thread, but for people using c#.NET whom might want to use the principals described in this thread, I Have some code for them ...

Code: Select all

using System;

namespace SpaceFlight { 
	public class Controls {
		public Controls() {
		}

		//--- move ship acording to its rotation ---
		public static void Move(Irrlicht.Scene.ISceneNode node, Irrlicht.Core.Vector3D vel) {
			Irrlicht.Core.Matrix4 m = new Irrlicht.Core.Matrix4();
			m.SetRotationDegrees( node.Rotation );
			m.TransformVect( ref vel );
			Irrlicht.Core.Vector3D Pos = node.Position;
			Pos.X += vel.X;
			Pos.Y += vel.Y;
			Pos.Z += vel.Z;
			node.Position = Pos;
		}

		//--- rotate node relative to its current rotation -used in turn,pitch,roll ---
		public static void Rotate(Irrlicht.Scene.ISceneNode node, Irrlicht.Core.Vector3D rot) {
			Irrlicht.Core.Matrix4 m = node.RelativeTransformation;
			Irrlicht.Core.Matrix4 n = new Irrlicht.Core.Matrix4();
			n.SetRotationDegrees(rot);
			m *= n;
			node.Rotation = getRotationDegrees( m );
		}

		//--- turn ship left or right ---
		public static void Turn(Irrlicht.Scene.ISceneNode node, float rot) {
			Rotate(node, new Irrlicht.Core.Vector3D(0.0f, rot, 0.0f) );
		}

		//--- pitch ship up or down ---
		public static void Pitch(Irrlicht.Scene.ISceneNode node, float rot) {
			Rotate(node, new Irrlicht.Core.Vector3D(rot, 0.0f, 0.0f) );
		}

		//--- roll ship left or right ---
		public static void Roll(Irrlicht.Scene.ISceneNode node, float rot) {
			Rotate(node, new Irrlicht.Core.Vector3D(0.0f, 0.0f, rot) );
		}

		// Missing getRotationDegrees Function for Matrix4 in .NET
		private static Irrlicht.Core.Vector3D getRotationDegrees( Irrlicht.Core.Matrix4 mat ) {
			const double GRAD_PI = 180.000f/Math.PI;
			double Y = - Math.Asin( mat.get_M(2,0) ); 
			double D = Y; 
			double C = Math.Cos(Y); 
			Y *= GRAD_PI;

			double rotx, roty, X, Z; 

			if ( Math.Abs(C) >0.0005f) {
				rotx = mat.get_M(2,2) / C; 
				roty = mat.get_M(2,1)  / C; 
				X = Math.Atan2( roty, rotx ) * GRAD_PI; 
				rotx = mat.get_M(0,0) / C; 
				roty = mat.get_M(1,0) / C; 
				Z = Math.Atan2( roty, rotx ) * GRAD_PI; 
			} else { 
				X  = 0.0f; 
				rotx = mat.get_M(1,1);
				roty = -mat.get_M(0,1);
				Z  = Math.Atan2( roty, rotx ) * (float)GRAD_PI; 
			} 

			if (X < 0.00) X += 360.00; 
			if (Y < 0.00) Y += 360.00; 
			if (Z < 0.00) Z += 360.00; 

			return new Irrlicht.Core.Vector3D((float)X,(float)Y,(float)Z);
		}
	}
}
I've basically taken the Code on this thread and written it into c# ....

Most .NET Programmers will be able to translate this into VB.NET If ther with ....


Hope this helps ...
Post Reply