Jump to content
madrussian

Quaternion Rotation functions [Release]

Recommended Posts

Here are a handful of functions I wrote a while back that I figure might help some folks out.  MRU_V3_QRotation is the big one.

 

Rotate a 3D vector around any axis in 3D space by any number of degrees.  Useful in both world space and model space.  [Feel free to use these in any way you see fit.  If you use in a release, please add simple credit, as these took a while to develop.]

 

Here ya go.  Have fun! :smile_o:

 

MRU_Q_Conjugate = {
	// MRU_Q_Conjugate by MadRussian (created long ago, updated 2/11/19)
	// This returns a simple quaternion conjugate.
	// Call with: [Quaternion] call MRU_Q_Conjugate;
	// Example: _quaternionConjugate = [[1,1,1,0]] call MRU_Q_Conjugate;
	// Result is [-1,-1,-1,0]

	private ["_x","_y","_z","_w"];

	params ["_Q"];

	_x = -(_Q select 0);
	_y = -(_Q select 1);
	_z = -(_Q select 2);
	_w = (_Q select 3);

	[_x, _y ,_z ,_w]
};

MRU_Q_FromV3 = {
	// MRU_Q_FromV3 by MadRussian (created long ago, updated 2/11/19)
	// This is a simple vector to quaternion conversion.
	// Call with: [Vector3] call MRU_Q_FromV3;
	// Example: _quaternion = [[1,1,1]] call MRU_Q_FromV3;
	// Result is [1,1,1,0]

	params ["_V"];

	[_V select 0, _V select 1, _V select 2, 0]
};

MRU_Q_Multiply = {
	// MRU_Q_Multiply by MadRussian (created long ago, updated 2/11/19)
	// This performs a simple quaternion multiplication.
	// Call with: [Quaternion1, Quaternion2] call MRU_Q_Multiply;
	// Example: _quaternion = [ [1,1,1,0], [0,0,0,1] ] call MRU_Q_Multiply;
	// Result is [1,1,1,0]

	private ["_x","_y","_z","_w"];

	params ["_qA","_qB"];

	_x = (_qA select 3)*(_qB select 0) + (_qA select 0)*(_qB select 3) + (_qA select 1)*(_qB select 2) - (_qA select 2)*(_qB select 1);
	_y = (_qA select 3)*(_qB select 1) - (_qA select 0)*(_qB select 2) + (_qA select 1)*(_qB select 3) + (_qA select 2)*(_qB select 0);
	_z = (_qA select 3)*(_qB select 2) + (_qA select 0)*(_qB select 1) - (_qA select 1)*(_qB select 0) + (_qA select 2)*(_qB select 3);
	_w = (_qA select 3)*(_qB select 3) - (_qA select 0)*(_qB select 0) - (_qA select 1)*(_qB select 1) - (_qA select 2)*(_qB select 2);

	[_x, _y, _z, _w]
};

MRU_Q_Normalize = {
	// MRU_Q_Normalize by MadRussian (created long ago, updated 2/11/19)
	// This performs a simple quaternion normalize.
	// Call with: [Quaternion] call MRU_Q_Normalize;
	// Example: _quaternionNormal = [[7,0,0,0]] call MRU_Q_Normalize;
	// Result is [1,0,0,0]

	private ["_l","_result"];

	params ["_Q"];

	_l = sqrt ( (_Q select 0)*(_Q select 0) + (_Q select 1)*(_Q select 1) + (_Q select 2)*(_Q select 2) + (_Q select 3)*(_Q select 3) );

	_result = [0,0,0,0];
	if (_l != 0) then { _result = [(_Q select 0)/_l, (_Q select 1)/_l, (_Q select 2)/_l, (_Q select 3)/_l] };

	_result
};

MRU_V3_QRotation = {
	// MRU_V3_QRotation by MadRussian (created long ago, updated 2/11/19)
	// This performs a simple(?) quaternion rotation.
	// Call with: [OrigVector, RotationAxis, RotationAngle] call MRU_V3_QRotation;
	//  where OrigVector is the original 3D vector to be translated
	//        RotationAxis is the rotational axis to be rotated about, represented by a 3D vector
	//        RotationalAngle is the angle to rotate by in degrees
	//
	// Example: _vector3 = [ [0,0,1], [1,0,0], 90 ] call MRU_V3_QRotation;
	//		would result in a rotated 3D vector of [0,1,0]

	private ["_origQ","_rotAxisQ","_rotAxisNormQ","_sinAD","_rotAxisTransQ","_rotAxisConjQ","_preResultQ","_resultQ"];

	params ["_origV","_rotAxis","_rotAng"];

	_origQ = [_origV] call MRU_Q_FromV3;
	_rotAxisQ = [_rotAxis] call MRU_Q_FromV3;

	_rotAxisNormQ = [_rotAxisQ] call MRU_Q_Normalize;
	_sinAD = sin(_rotAng/2);
	_rotAxisTransQ = [ (_rotAxisNormQ select 0)*_sinAD, (_rotAxisNormQ select 1)*_sinAD, (_rotAxisNormQ select 2)*_sinAD, cos(_rotAng/2) ];
	_rotAxisConjQ = [_rotAxisTransQ] call MRU_Q_Conjugate;

	_preResultQ = [_rotAxisTransQ, _origQ] call MRU_Q_Multiply;
	_resultQ = [_preResultQ, _rotAxisConjQ] call MRU_Q_Multiply;

	[_resultQ select 0, _resultQ select 1, _resultQ select 2]
};

 

Update 2/11/19: Cleaned up the comments & examples, removed an empty private block.

 

  • Like 3
  • Thanks 2

Share this post


Link to post
Share on other sites

Sweet!  Thanks man.  I've been wanting to simply rotate by degrees forever.

  • Like 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×