diff --git a/addons/vectors/fnc_vectRotate3D.sqf b/addons/vectors/fnc_vectRotate3D.sqf new file mode 100644 index 000000000..9de4e1a78 --- /dev/null +++ b/addons/vectors/fnc_vectRotate3D.sqf @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------------- +Function: CBA_vectors_fnc_vectRotate3D + +Description: + Rotates the first vector around the second, clockwise by theta degrees. + +Parameters: + _vector - 3D vector that is to be rotated + _rotationAxis - 3D vector that the first argument is rotated around + _theta - Angle, in degrees clockwise, about which the first vector is rotated + +Returns: + _returnVector - 3D vector returned after rotation + +Examples: + (begin example) + //Rotate 25 degrees right of player weapon direction; + [weaponDirection player, [0,0,1], 25] call CBA_vectors_fnc_vectRotate3D; + + //Pitch a projectile's velocity down 10 degrees; + [velocity _projectile, (velocity _projectile) vectorCrossProduct [0,0,1], 10] call CBA_vectors_fnc_vectRotate3D; + (end) + +Author: + LorenLuke +---------------------------------------------------------------------------- */ +#include "script_component.hpp" + +params ["_vector", "_rotationAxis", "_theta"]; + +private _normalVector = vectorNormalized _rotationAxis; +private _sinTheta = sin _theta; +private _cosTheta = cos _theta; + +// Rodrigues Rotation Formula; +// https://wikimedia.org/api/rest_v1/media/math/render/svg/2d63efa533bdbd776434af1a7af3cdafaff1d578 +(_vector vectorMultiply _cosTheta) vectorAdd +((_normalVector vectorCrossProduct _vector) vectorMultiply _sinTheta) vectorAdd +(_normalVector vectorMultiply ((_normalVector vectorDotProduct _vector) * (1 - _cosTheta))) diff --git a/addons/vectors/test_vectors.sqf b/addons/vectors/test_vectors.sqf index 42167cac5..7431bcc33 100644 --- a/addons/vectors/test_vectors.sqf +++ b/addons/vectors/test_vectors.sqf @@ -247,6 +247,33 @@ _result = [[5,-5],[-10,0],-270] call CBA_fnc_vectRotate2D; _expected = [0,-20]; TEST_TRUE([ARR_2(_result,_expected)] call _fnc_vectorEquals,_fn); +// UNIT TESTS (vectRotate3D) +_fn = "CBA_fnc_vectRotate3D"; +TEST_DEFINED("CBA_fnc_vectRotate3D",""); + +_result = [[0,0,1],[0,0,1],0] call CBA_fnc_vectRotate3D; +_expected = [0,0,1]; +TEST_TRUE([ARR_2(_result,_expected)] call _fnc_vectorEquals,_fn); + +_result = [[0,0,1],[0,0,1],90] call CBA_fnc_vectRotate3D; +_expected = [0,0,1]; +TEST_TRUE([ARR_2(_result,_expected)] call _fnc_vectorEquals,_fn); + +_result = [[0,1,0],[0,0,-1],90] call CBA_fnc_vectRotate3D; +_expected = [1,0,0]; +TEST_TRUE([ARR_2(_result,_expected)] call _fnc_vectorEquals,_fn); + +_result = [[0,1,0],[0,0,-10],90] call CBA_fnc_vectRotate3D; +_expected = [1,0,0]; +TEST_TRUE([ARR_2(_result,_expected)] call _fnc_vectorEquals,_fn); + +_result = [[0,1,0],[1,0,0],90] call CBA_fnc_vectRotate3D; +_expected = [0,0,1]; +TEST_TRUE([ARR_2(_result,_expected)] call _fnc_vectorEquals,_fn); + +_result = [[0,1,0],[0,0,1],-45] call CBA_fnc_vectRotate3D; +_expected = [0,sqrt(2)/2,sqrt(2)/2]; +TEST_TRUE([ARR_2(_result,_expected)] call _fnc_vectorEquals,_fn); // UNIT TESTS (vectSubtract) _fn = "CBA_fnc_vectSubtract"; @@ -269,4 +296,4 @@ _result = _temp call CBA_fnc_polar2vect; TEST_TRUE([ARR_2(_result,_expected)] call _fnc_vectorEquals, "complex polar 2"); -nil; \ No newline at end of file +nil;