@@ -14,23 +14,152 @@ namespace hlsl
1414namespace math
1515{
1616
17+ template<typename T>
18+ struct truncated_quaternion
19+ {
20+ using this_t = truncated_quaternion<T>;
21+ using scalar_type = T;
22+ using data_type = vector <T, 3 >;
23+
24+ static this_t create ()
25+ {
26+ this_t q;
27+ q.data = data_type (0.0 , 0.0 , 0.0 );
28+ return q;
29+ }
30+
31+ data_type data;
32+ };
33+
1734template <typename T>
18- struct quaternion_t
35+ struct quaternion
1936{
20- using this_t = quaternion_t <T>;
37+ using this_t = quaternion <T>;
2138 using scalar_type = T;
2239 using data_type = vector <T, 4 >;
2340 using vector3_type = vector <T, 3 >;
2441 using matrix_type = matrix <T, 3 , 3 >;
2542
26- static this_t createFromTruncated (const vector3_type first3Components)
43+ static this_t create ()
44+ {
45+ this_t q;
46+ q.data = data_type (0.0 , 0.0 , 0.0 , 1.0 );
47+ return q;
48+ }
49+
50+ static this_t create (scalar_type x, scalar_type y, scalar_type z, scalar_type w)
51+ {
52+ this_t q;
53+ q.data = data_type (x, y, z, w);
54+ return q;
55+ }
56+
57+ static this_t create (NBL_CONST_REF_ARG (this_t) other)
58+ {
59+ return other;
60+ }
61+
62+ static this_t create (scalar_type pitch, scalar_type yaw, scalar_type roll)
63+ {
64+ const scalar_type rollDiv2 = roll * scalar_type (0.5 );
65+ const scalar_type sr = hlsl::sin (rollDiv2);
66+ const scalar_type cr = hlsl::cos (rollDiv2);
67+
68+ const scalar_type pitchDiv2 = pitch * scalar_type (0.5 );
69+ const scalar_type sp = hlsl::sin (pitchDiv2);
70+ const scalar_type cp = hlsl::cos (pitchDiv2);
71+
72+ const scalar_type yawDiv2 = yaw * scalar_type (0.5 );
73+ const scalar_type sy = hlsl::sin (yawDiv2);
74+ const scalar_type cy = hlsl::cos (yawDiv2);
75+
76+ this_t output;
77+ output.data[0 ] = cr * sp * cy + sr * cp * sy; // x
78+ output.data[1 ] = cr * cp * sy - sr * sp * cy; // y
79+ output.data[2 ] = sr * cp * cy - cr * sp * sy; // z
80+ output.data[3 ] = cr * cp * cy + sr * sp * sy; // w
81+
82+ return output;
83+ }
84+
85+ static this_t create (NBL_CONST_REF_ARG (matrix_type) m)
86+ {
87+ using AsUint = typename unsigned_integer_of_size<sizeof (scalar_type)>::type;
88+ const scalar_type m00 = m[0 ][0 ], m11 = m[1 ][1 ], m22 = m[2 ][2 ];
89+ const scalar_type neg_m00 = bit_cast<scalar_type>(bit_cast<AsUint>(m00)^0x80000000u);
90+ const scalar_type neg_m11 = bit_cast<scalar_type>(bit_cast<AsUint>(m11)^0x80000000u);
91+ const scalar_type neg_m22 = bit_cast<scalar_type>(bit_cast<AsUint>(m22)^0x80000000u);
92+ const data_type Qx = data_type (m00, m00, neg_m00, neg_m00);
93+ const data_type Qy = data_type (m11, neg_m11, m11, neg_m11);
94+ const data_type Qz = data_type (m22, neg_m22, neg_m22, m22);
95+
96+ const data_type tmp = hlsl::promote<data_type>(1.0 ) + Qx + Qy + Qz;
97+ const data_type invscales = hlsl::promote<data_type>(0.5 ) / hlsl::sqrt (tmp);
98+ const data_type scales = tmp * invscales * hlsl::promote<data_type>(0.5 );
99+
100+ // TODO: speed this up
101+ this_t retval;
102+ if (tmp.x > scalar_type (0.0 ))
103+ {
104+ retval.data.x = (m[2 ][1 ] - m[1 ][2 ]) * invscales.x;
105+ retval.data.y = (m[0 ][2 ] - m[2 ][0 ]) * invscales.x;
106+ retval.data.z = (m[1 ][0 ] - m[0 ][1 ]) * invscales.x;
107+ retval.data.w = scales.x;
108+ }
109+ else
110+ {
111+ if (tmp.y > scalar_type (0.0 ))
112+ {
113+ retval.data.x = scales.y;
114+ retval.data.y = (m[0 ][1 ] + m[1 ][0 ]) * invscales.y;
115+ retval.data.z = (m[2 ][0 ] + m[0 ][2 ]) * invscales.y;
116+ retval.data.w = (m[2 ][1 ] - m[1 ][2 ]) * invscales.y;
117+ }
118+ else if (tmp.z > scalar_type (0.0 ))
119+ {
120+ retval.data.x = (m[0 ][1 ] + m[1 ][0 ]) * invscales.z;
121+ retval.data.y = scales.z;
122+ retval.data.z = (m[0 ][2 ] - m[2 ][0 ]) * invscales.z;
123+ retval.data.w = (m[1 ][2 ] + m[2 ][1 ]) * invscales.z;
124+ }
125+ else
126+ {
127+ retval.data.x = (m[0 ][2 ] + m[2 ][0 ]) * invscales.w;
128+ retval.data.y = (m[1 ][2 ] + m[2 ][1 ]) * invscales.w;
129+ retval.data.z = scales.w;
130+ retval.data.w = (m[1 ][0 ] - m[0 ][1 ]) * invscales.w;
131+ }
132+ }
133+
134+ retval.data = hlsl::normalize (retval.data);
135+ return retval;
136+ }
137+
138+ static this_t createFromTruncated (NBL_CONST_REF_ARG (truncated_quaternion<T>) first3Components)
27139 {
28140 this_t retval;
29- retval.data.xyz = first3Components;
30- retval.data.w = hlsl::sqrt (scalar_type (1.0 ) - hlsl::dot (first3Components, first3Components));
141+ retval.data.xyz = first3Components.data ;
142+ retval.data.w = hlsl::sqrt (scalar_type (1.0 ) - hlsl::dot (first3Components.data , first3Components.data ));
31143 return retval;
32144 }
33145
146+ this_t operator*(scalar_type scalar)
147+ {
148+ this_t output;
149+ output.data = data * scalar;
150+ return output;
151+ }
152+
153+ this_t operator*(NBL_CONST_REF_ARG (this_t) other)
154+ {
155+ return this_t::create (
156+ data.w * other.data.w - data.x * other.x - data.y * other.data.y - data.z * other.data.z,
157+ data.w * other.data.x + data.x * other.w + data.y * other.data.z - data.z * other.data.y,
158+ data.w * other.data.y - data.x * other.z + data.y * other.data.w + data.z * other.data.x,
159+ data.w * other.data.z + data.x * other.y - data.y * other.data.x + data.z * other.data.w
160+ );
161+ }
162+
34163 static this_t lerp (const this_t start, const this_t end, const scalar_type fraction, const scalar_type totalPseudoAngle)
35164 {
36165 using AsUint = typename unsigned_integer_of_size<sizeof (scalar_type)>::type;
0 commit comments