moving a vehicle forward while pitching and rolling

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
ice
Posts: 6
Joined: Mon Sep 18, 2006 3:43 pm

moving a vehicle forward while pitching and rolling

Post by ice »

Hi,
I have a vehicle moving on a plane and turning OK (around the Y axis), but now I want it to pitch it a little when accelerating (like an helicopter) and also roll it a litle bit when turning.

I'm using the standard setRotation() and the turning and rolling are working fine, but somehow the pitching isn't working properly.
What happens is that I'm getting different behaviours about the pitching angle depending on the turning (Y) angle.
So, let's say that I want it to pitch down -1º by -1º:

Code: Select all

rotation.setZ(rotation.getZ() - 1);
- when the vehicle Y rotation is zero, the pitching works fine and the nose goes down;
- when the vehicle turns left or right, -90º < Y < 90º, the nose goes less and less down;
- when the vehicle is facing the oposite direction, then the nose goes up;

So, when I move the vehicle around (changing direction), the pitching efect is not constant as I wanted it to be.

Any idea why this is happening and how can I solve this?

Thanks.
Warren
Posts: 60
Joined: Fri Jul 07, 2006 11:41 pm
Location: Santiago De Compostela, Spain

Post by Warren »

this is caused because irrlicht uses absolute coordinates, to make rotations properly in this case you need to use a physic engine like Newton
------------------------------------------------
Irrlicht Ussers Map
Join now!!
http://www.frappr.com/irrlichtusers
ice
Posts: 6
Joined: Mon Sep 18, 2006 3:43 pm

Post by ice »

hm.. I see..

but the problem is that I'm using Jirr. is there a JAVA binding for Newton, so that I can integrate it with Jirr?
Trikko
Posts: 5
Joined: Fri Oct 13, 2006 10:27 am

Post by Trikko »

Have you tried to use an empty node tree? You can use a node to roll, one to pitch etc... As long as movement is relative it should works fine...
CodeDog
Posts: 106
Joined: Sat Oct 07, 2006 8:00 pm
Location: CA. USA
Contact:

Post by CodeDog »

You're going to need some trig for this.
Let me see if I can point you in the right direction.

“Pseudcode”
Point3D loc; //point in 3d space i.e. x, y , z
Point3D lookat; //the point you are facing
Point3D up; //your up vector
Point3D rollaxis; //and how much you have rolled

#define M_PI (4*atan(1.0))
// change the pitch
void [yourclass]::pitch(float angle)
{
float tempx=up.x;
float tempy=up.y;
float tempz=up.z;
float cosine=cos(angle*M_PI/180.0);
float sine=sin(angle*M_PI/180.0);
up.x=tempx*cosine-lookat.x*sine;
up.y=tempy*cosine-lookat.y*sine;
up.z=tempz*cosine-lookat.z*sine;
lookat.x=tempx*sine+lookat.x*cosine;
lookat.y=tempy*sine+lookat.y*cosine;
lookat.z=tempz*sine+lookat.z*cosine;
}

// roll
void [yourclass]::roll(float angle)
{
float tempx=rollaxis.x;
float tempy=rollaxis.y;
float tempz=rollaxis.z;
float cosine=cos(angle*M_PI/180.0);
float sine=sin(angle*M_PI/180.0);
rollaxis.x=tempx*cosine-up.x*sine;
rollaxis.y=tempy*cosine-up.y*sine;
rollaxis.z=tempz*cosine-up.z*sine;
up.x=tempx*sine+up.x*cosine;
up.y=tempy*sine+up.y*cosine;
up.z=tempz*sine+up.z*cosine;
}

// yaw the left and right
void [yourclass]::yaw(float angle)
{
float tempx=rollaxis.x;
float tempy=rollaxis.y;
float tempz=rollaxis.z;
float cosine=cos(angle*M_PI/180.0);
float sine=sin(angle*M_PI/180.0);
rollaxis.x=tempx*cosine+lookat.x*sine;
rollaxis.y=tempy*cosine+lookat.y*sine;
rollaxis.z=tempz*cosine+lookat.z*sine;
lookat.x=-tempx*sine+lookat.x*cosine;
lookat.y=-tempy*sine+lookat.y*cosine;
lookat.z=-tempz*sine+lookat.z*cosine;
}
ice
Posts: 6
Joined: Mon Sep 18, 2006 3:43 pm

Post by ice »

great!
I assume that your Point3D is a vector3df, right?

also, how can I get the "lookat" and "up" vectors?

thanks.
CodeDog
Posts: 106
Joined: Sat Oct 07, 2006 8:00 pm
Location: CA. USA
Contact:

Post by CodeDog »

ice wrote:great!
I assume that your Point3D is a vector3df, right?

Yes you can use vector3df. I was using a simple class with 3 float x, y, z.
ice wrote: also, how can I get the "lookat" and "up" vectors?

thanks.
The code I posted was from an old OpenGL Camera class I made so yes it gives you the new UP and Look at vectors.
Would you like the source for the whole class? You'd need to change it to use irrlicht instead of OpenGL but the math remains the same.
BTW the camera was used in a space shooter I made as a demo, so it works like you want. I made a simple 3D asteroids game were you shoot the rocks and try not to run into them or the sun. There was simulated gravity and movement was done via a vector system with physics of my own design.

Point3D.h

Code: Select all

class Point3D
{
public:
	Point3D(void);
	~Point3D(void);
	double x;
	double y;
	double z;
	void SetPoint(double lx, double ly, double lz);
	CString toString(void);
	void operator= (const Point3D& aPoint3D); 
	Point3D(const Point3D& aPoint3D);
};
Point3D.cpp

Code: Select all

#include ".\point3d.h"

Point3D::Point3D(void)
: x(0)
, y(0)
, z(0)
{
}

Point3D::~Point3D(void)
{
}

void Point3D::SetPoint(double lx, double ly, double lz)
{
	x = lx;
	y = ly;
	z = lz;
}

CString Point3D::toString(void)
{
	CString str;
	str = "(";
	char buffer[25];
	_gcvt( x, 12, buffer );
	str = str + buffer;
	str = str + ", ";
	
	_gcvt( y, 12, buffer );
	str = str + buffer;
	str = str + ", ";

	_gcvt( z, 12, buffer );
	str = str + buffer;
	str = str + ")";



	
	return str;
}
void Point3D::operator= (const Point3D& aPoint3D) 
{
	x = aPoint3D.x;
	y = aPoint3D.y;
	z = aPoint3D.z;
}
Point3D::Point3D(const Point3D& aPoint3D)
{
	x = aPoint3D.x;
	y = aPoint3D.y;
	z = aPoint3D.z;
}
Camera.h

Code: Select all

#include "point3d.h"
// a camer class to make doing the spherical trig not quite as bad as sharp forks in my eyes
class Camera
{
	
public:
	Camera(void);
	Camera(float eyex, float eyey, float eyez);
	~Camera(void);
	// translate along x y and z axis
	void translate(float du, float dv, float dn);
	// change the pitch of the cam
	void pitch(float angle);
	// roll the camera
	void roll(float angle);
	// yaw the cam left and right
	void yaw(float angle);
	// do the lookat call
	void applyView(void);
	// current camera location, the lookat vector, up vector and roll displacment
	Point3D loc, lookat, up, rollaxis;
};
Camera.cpp

Code: Select all

#include ".\camera.h"
#include <math.h>
#include <gl\glut.h>
#ifndef M_PI
#define M_PI (4*atan(1.0))

#endif
//the default constructor
Camera::Camera(void)

{	
	rollaxis.x=1;
	rollaxis.y=0;
	rollaxis.z=0;
	up.x=0;
	up.y=1;
	up.z=0;
	lookat.x=0;
	lookat.y=0;
	lookat.z=-1;
}
//the copy constructor
Camera::Camera(float eyex,float eyey,float eyez)
{ 
	loc.x=eyex; loc.y=eyey; loc.z=eyez;
	rollaxis.x=1;rollaxis.y=0;rollaxis.z=0;up.x=0;up.y=1;up.z=0;lookat.x=0;lookat.y=0;lookat.z=-1;
}

Camera::~Camera(void)
{
}

// translate along x y and z axis
void Camera::translate(float du, float dv, float dn)
{
	loc.x+=(du*rollaxis.x+dv*up.x+dn*lookat.x);
	loc.y+=(du*rollaxis.y+dv*up.y+dn*lookat.y);
	loc.z+=(du*rollaxis.z+dv*up.z+dn*lookat.z);
}

// change the pitch of the cam
void Camera::pitch(float angle)
{
	float tempx=up.x;
		float tempy=up.y;
		float tempz=up.z;
		float cosine=cos(angle*M_PI/180.0);
		float sine=sin(angle*M_PI/180.0);
		up.x=tempx*cosine-lookat.x*sine;
		up.y=tempy*cosine-lookat.y*sine;
		up.z=tempz*cosine-lookat.z*sine;
		lookat.x=tempx*sine+lookat.x*cosine;
		lookat.y=tempy*sine+lookat.y*cosine;
		lookat.z=tempz*sine+lookat.z*cosine;
}

// roll the camera
void Camera::roll(float angle)
{
	float tempx=rollaxis.x;
	float tempy=rollaxis.y;
	float tempz=rollaxis.z;
	float cosine=cos(angle*M_PI/180.0);
	float sine=sin(angle*M_PI/180.0);
	rollaxis.x=tempx*cosine-up.x*sine;
	rollaxis.y=tempy*cosine-up.y*sine;
	rollaxis.z=tempz*cosine-up.z*sine;
	up.x=tempx*sine+up.x*cosine;
	up.y=tempy*sine+up.y*cosine;
	up.z=tempz*sine+up.z*cosine;
}

// yaw the cam left and right
void Camera::yaw(float angle)
{
	float tempx=rollaxis.x;
	float tempy=rollaxis.y;
	float tempz=rollaxis.z;
	float cosine=cos(angle*M_PI/180.0);
	float sine=sin(angle*M_PI/180.0);
	rollaxis.x=tempx*cosine+lookat.x*sine;
	rollaxis.y=tempy*cosine+lookat.y*sine;
	rollaxis.z=tempz*cosine+lookat.z*sine;
	lookat.x=-tempx*sine+lookat.x*cosine;
	lookat.y=-tempy*sine+lookat.y*cosine;
	lookat.z=-tempz*sine+lookat.z*cosine;
}

// do the lookat call

void Camera::applyView(void)
{
	//eye, lookat point, up vector
	gluLookAt(loc.x,loc.y,loc.z,loc.x+lookat.x,loc.y+lookat.y,loc.z+lookat.z,up.x,up.y,up.z);
}
Duncan Mac Leod
Posts: 64
Joined: Sun May 22, 2005 3:06 pm
Location: Germany
Contact:

Post by Duncan Mac Leod »

Trikko wrote:Have you tried to use an empty node tree? You can use a node to roll, one to pitch etc... As long as movement is relative it should works fine...
That's IMHO the best and easiest way :wink: ...
CodeDog
Posts: 106
Joined: Sat Oct 07, 2006 8:00 pm
Location: CA. USA
Contact:

Post by CodeDog »

Duncan Mac Leod wrote:
Trikko wrote:Have you tried to use an empty node tree? You can use a node to roll, one to pitch etc... As long as movement is relative it should works fine...
That's IMHO the best and easiest way :wink: ...
Unfortunately, it doesn’t work in practice.
Order matters, and with chained nodes you are always assuming that rotations will be applied in the same order every time but in a game the rotations will happen in a random order.
Roll 45, Yaw 45 pitch -45 wont point you in the same direction as
Pitch -45 Yaw, 45 Roll, 45.
One will point you down and the other will put you sideways and point somewhat to the right.
So you need an order independent method of orienting your node and for that you need to calculate all three axis at the same time. Well, actually you need 4 axis in order to prevent gimble lock.
If you want you can check out my camera in action.
http://www.kencocomputers.com/tutorials/SpaceArt.zip
ice
Posts: 6
Joined: Mon Sep 18, 2006 3:43 pm

Post by ice »

thanks again CodeDog, but I'm having trouble in "decoding" what you have and applying it to my problem.

what I have is a vehicle with a cam attached, so that when I move the vehicle the cam comes along. the cam doesn't rotate either. it simply follows the vehicle in a horizontal position.
for the vehicle I have a setPosition(x, ,y, z) and a setRotation(x, y, z).

I just want to know how to apply the correct rotation to the vehicle so that the vehicle can pitch down a little while going forward.

I think I cannot have up, lookat and rollaxis vectors for the vehicle because it doesn't behave like a cam.

can you help me on this?

thanks.
CodeDog
Posts: 106
Joined: Sat Oct 07, 2006 8:00 pm
Location: CA. USA
Contact:

Post by CodeDog »

You could use core::vector3df.
It has a function getHorizontalAngle().
Post Reply