-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathquaternionRotations.pas
67 lines (53 loc) · 2.2 KB
/
quaternionRotations.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
unit quaternionRotations; // Quaternions are used to rotate a 3d object
//-----------------------//
// in multiple axis.
// Warning: Using RotationAngle (Euler angles) can generate gymbal locks and weird movements
// source: github.com/omarreis/vsop2013/
// programmed by oMAR
// Hisory:
// set20: start
//------------------------------------------------------------------------------------
interface
uses
System.Math.Vectors, // TQuaternion3D
FMX.Controls3D;
// Usage sample:
// Q:TQuaiternion3D;
// ToQuaternion({roll:}aSensorVec.z,{pitch:} aSensorVec.y {aSensorVec.y},{yaw:}aSensorVec.x, Q );
// dummyAirliner.SetMatrix(Q); // rotate camera pointing to boat using quaternion
type // helper class to help manipulating the matrix instead of changing RotationAngle
TControl3DHelper = class helper for TControl3D
procedure SetMatrix(const M: TMatrix3D);
end;
procedure ToQuaternion(const yaw,pitch,roll:Single; var q:TQuaternion3D); // yaw (Z), pitch (Y), roll (X)
implementation //----------------------------------------------------------
function deg2rad(const d:Single):Single;
begin
Result := d/180*3.14159265;
end;
// from wikipedia https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
// by experience I found that this is more like ToQuaternion(roll,pitch,yaw) or (z,x,y)
// confusing ..
procedure ToQuaternion(const yaw,pitch,roll:Single; var q:TQuaternion3D); // yaw (Z), pitch (Y), roll (X)
var cy,sy,cp,sp,cr,sr,y,p,r:Single;
begin // Abbreviations for the various angular functions
y := deg2rad(yaw); // deg to rad
p := deg2rad(pitch);
r := deg2rad(roll);
cy := cos(y * 0.5); sy := sin(y * 0.5); // memoise trigs
cp := cos(p * 0.5); sp := sin(p * 0.5);
cr := cos(r * 0.5); sr := sin(r * 0.5);
q.RealPart := cr * cp * cy + sr * sp * sy; // mk quaternion
q.ImagPart.x := sr * cp * cy - cr * sp * sy;
q.ImagPart.y := cr * sp * cy + sr * cp * sy;
q.ImagPart.z := cr * cp * sy - sr * sp * cy;
end;
{ TControl3DHelper }
procedure TControl3DHelper.SetMatrix(const M: TMatrix3D);
begin
FLocalMatrix := M;
RecalcAbsolute;
RebuildRenderingList;
Repaint;
end;
end.