# Set pitch / bank functions

## Recommended Posts

----------------------------------------------------

*Updated 20 June 2008*

FIXED: Possible divide-by-zero error in get function

FIXED: Bank wasn't being set or retrieved accurately

Big thanks to vektorboson for correcting my math!

----------------------------------------------------

Hello all!

I don't know about you, but personally I've struggled quite a bit with the setVectorDir, setVectorUp, and setVectorDirAndUp commands. I'm sure they are quite perfect for certain uses; but personally, I want to work in degrees, and I want it to be relative to the object's facing.

So, after MUCH struggle (I'm sure it would have been easy for someone good at math), I've created the following function. I hope you find it useful!

This function lets you set an object's pitch and bank, in degrees:

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">

/************************************************************

Set Pitch and Bank

By General Barron (aw_barron@hotmail.com) and vektorboson

Parameters: [object, pitch, bank]

Returns: nothing

Rotates an object, giving it the specified pitch and bank,

in degrees.

Pitch is 0 when the object is level; 90 when pointing straight

up; and -90 when pointing straight down.

Bank is 0 when level; 90 when the object is rolled to the right,

-90 when rolled to the left, and 180 when rolled upside down.

Note that the object's yaw can be set with the setdir command,

which should be issued before using this function, if required.

The pitch/bank can be leveled out (set to 0) by using the

setdir command.

************************************************************/

//extract parameters

private ["_obj","_pitch","_bank","_yaw","_vdir","_vup","_sign","_rotate"];

_obj = _this select 0;

_pitch = _this select 1;

_bank = _this select 2;

//find the yaw (direction) of the object

//map compass directions go CW, while coordinate (vector) directions go CCW, so we need to flip this

//if we don't flip this, the object will face backwards

_yaw = 360-(getdir _obj);

//----------------------------

//function to rotate a 2d vector around the origin

//----------------------------

_rotate =

{

private ["_v","_d","_x","_y"];

//extract parameters

_v = +(_this select 0); //we don't want to modify the originally passed vector

_d = _this select 1;

//extract old x/y values

_x = _v select 0;

_y = _v select 1;

//if vector is 3d, we don't want to mess up the last element

_v set [0, (cos _d)*_x - (sin _d)*_y];

_v set [1, (sin _d)*_x + (cos _d)*_y];

//return new vector

_v

};

//----------------------------

//find vector dir (pitch)

//----------------------------

//find sign of pitch

_sign = [1,-1] select (_pitch < 0);

//cut off numbers above 180

while {abs _pitch > 180} do {_pitch = _sign*(abs _pitch - 180)};

//we can't use pitch that is exactly equal to 90, because then the engine doesn't know what 2d compass direction the object is facing

if(abs _pitch == 90) then {_pitch = _sign*(89.9)};

//we can't pitch beyond 90 degrees without changing the facing of our object

//(pitching beyond 90 degrees means that the object's eyes will point in the 2d compass direction that its back used to point)

if(abs _pitch > 90) then

{

//we are rolling upside down; flip our direction (yaw)

_obj setdir (getdir _obj)-180;

_yaw = 360-(getdir _obj);

//use bank to flip upside down

_bank = _bank + 180;

_pitch = (180 - abs _pitch)*_sign;

};

//find appropriate vdir according to our pitch, as if we were facing north

_vdir = [0, cos _pitch, sin _pitch];

//then rotate X & Y around the origin according to object's yaw (direction)

_vdir = [_vdir, _yaw] call _rotate;

//----------------------------

//find vector up (bank)

//----------------------------

//find sign of bank

_sign = [1,-1] select (_bank < 0);

//cut off numbers above 360

while {abs _bank > 360} do {_bank = _sign*(abs _bank - 360)};

//reflect numbers above 180

if(abs _bank > 180) then {_sign = -1*_sign; _bank = (360-_bank)*_sign};

//find appropriate vup according to our bank, as if we were facing north

_vup = [sin _bank, 0, cos _bank];

//rotate Y & Z elements according to pitch

_vup = [_vup select 0] + ([[_vup select 1, _vup select 2], _pitch] call _rotate);

//rotate X & Y around origin according to yaw

_vup = [_vup, _yaw] call _rotate;

//----------------------------

//apply the vectors

//----------------------------

_obj setVectorDirAndUp [_vdir, _vup];

-----------------------------------------

An example of use:

-Save the code as "setPitchBank.sqf" in your mission directory.

-In init.sqf, write the following:

setPitchBank = compile preprocessfile "setPitchBank.sqf"

-In a script somewhere, write something such as:

[player, 45, -15] call setPitchBank

-----------------------------------------

This function lets you GET an object's pitch and bank, in degrees.

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">

/************************************************************

Get Pitch and Bank

By General Barron (aw_barron@hotmail.com) and vektorboson

Parameters: object

Returns: [pitch, bank]

Returns the pitch and bank of an object, in degrees.

Yaw can be found using the getdir command.

Pitch is 0 when the object is level; 90 when pointing straight

up; and -90 when pointing straight down.

Bank is 0 when level; 90 when the object is rolled to the right,

-90 when rolled to the left, and 180 when rolled upside down.

************************************************************/

//extract parameters

private ["_obj","_pitch","_bank","_yaw","_vdir","_vup","_sign", "_rotate"];

_obj = _this;

//find the yaw (direction) of the object

//note that map compass directions go CW, while coordinate (vector) directions go CCW

//so when we rotate vectors by this much (below), we are actually adjusting the vector as though the object were pointing north

_yaw = getdir _obj;

//----------------------------

//function to rotate a 2d vector around the origin

//----------------------------

_rotate =

{

private ["_v","_d","_x","_y"];

//extract parameters

_v = +(_this select 0); //we don't want to modify the originally passed vector

_d = _this select 1;

//extract old x/y values

_x = _v select 0;

_y = _v select 1;

//if vector is 3d, we don't want to mess up the last element

_v set [0, (cos _d)*_x - (sin _d)*_y];

_v set [1, (sin _d)*_x + (cos _d)*_y];

//return new vector

_v

};

//----------------------------

//find pitch

//----------------------------

//get vector dir (pitch)

_vdir = vectordir _obj;

//rotate X & Y around the origin according to the object's yaw (direction)

//we will then be left with the objects vectordir if it were facing north

_vdir = [_vdir, _yaw] call _rotate;

//if we reverse the process we used to set pitch when facing north, we can now get pitch

if ((_vdir select 1) != 0) then

{

_pitch = atan ((_vdir select 2) / (_vdir select 1));

}

else

{

//we need a fail-safe here to prevent divide-by-zero errors

//if X is zero, that means pitch is +/-90, we just need to figure out which one

if ((_vdir select 2) >= 0) then {_pitch = 90} else {_pitch = -90};

};

//----------------------------

//find bank

//----------------------------

//get vector up (bank)

_vup = vectorup _obj;

//rotate X & Y around the origin according to the object's yaw (direction)

//we will then be left with the objects vectorup if it were facing north

_vup = [_vup, _yaw] call _rotate;

//rotate Y & Z around according to the object's pitch

_vup = [_vup select 0] + ([[_vup select 1, _vup select 2], 360-_pitch] call _rotate);

//if we reverse the process we used to set bank when facing north, we can now get bank

if ((_vup select 2) != 0) then

{

_bank = atan ((_vup select 0) / (_vup select 2));

}

else

{

//we need a fail-safe here to prevent divide-by-zero errors

//if Z is zero, that means bank is +/-90, we just need to figure out which one

if ((_vdir select 2) >= 0) then {_bank = 90} else {_bank = -90};

};

//if we are rolled over (abs bank > 90), we need to adjust our result

if((_vup select 2) < 0) then

{

_sign = [1,-1] select (_bank < 0);

_bank = _bank - _sign*180;

};

//----------------------------

//return value

//----------------------------

[_pitch, _bank];

##### Share on other sites

That sounds excellent.

I noticed a call to fn_vbs_rotateVector2D. Is that a publicly available function somewhere?

##### Share on other sites

The content of _rotate comprises what is found within fn_vbs_rotateVector2D, so

<table border="0" align="center" width="95%" cellpadding="0" cellspacing="0"><tr><td>Code Sample </td></tr><tr><td id="CODE">

_local = [] call _rotate;

would be an appropriate replacement, just do a search and replace.

##### Share on other sites

very cool, I have been trying to even out fences for ever

##### Share on other sites
That sounds excellent.

I noticed a call to fn_vbs_rotateVector2D. Is that a publicly available function somewhere?

Whoops, looks like I missed that one in the conversion. As shinRaiden said, it is the _rotate function. I'll modify my original post.

##### Share on other sites

thanks Barron

so you just put the line into the objects init line?

and choose what angle I need in the script.

##### Share on other sites

Big, big, big, huge thanks to vektorboson, who actually knows math and corrected the bugs in my functions!

I've updated the first post, the functions are now 100% correct, there were bugs before with the getting and setting of bank, depending on pitch.

Again, major thanks to vektorboson for the help!

##### Share on other sites

GB, Thanks a million for this. I find setVector commands completely baffling, and the trial and error to place objects is murder. Your function really makes this easy for me now.

##### Share on other sites

Hello,

many thanks to GB & VB for this very nice stuff

I have add this function to 3DE now and it works exactly as it should.

The possibilities are considerably increased

Greeting

Silola