General Barron 0 Posted May 6, 2008 ---------------------------------------------------- *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; //and adjust our original pitch _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 this post Link to post Share on other sites
dr_eyeball 16 Posted May 6, 2008 That sounds excellent. I noticed a call to fn_vbs_rotateVector2D. Is that a publicly available function somewhere? Share this post Link to post Share on other sites
shinRaiden 0 Posted May 6, 2008 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 this post Link to post Share on other sites
dachevs 1 Posted May 7, 2008 very cool, I have been trying to even out fences for ever Share this post Link to post Share on other sites
General Barron 0 Posted May 7, 2008 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 this post Link to post Share on other sites
dachevs 1 Posted May 7, 2008 thanks Barron so you just put the line into the objects init line? and choose what angle I need in the script. Share this post Link to post Share on other sites
General Barron 0 Posted June 20, 2008 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 this post Link to post Share on other sites
johnnyboy 3793 Posted June 20, 2008 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 this post Link to post Share on other sites
silola 1086 Posted July 22, 2008 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 Share this post Link to post Share on other sites