1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "base/geometry/transform_util.h"
17
18 namespace OHOS::Ace {
19 namespace {
20
Length3(const float v[3])21 float Length3(const float v[3])
22 {
23 double vd[3] = { v[0], v[1], v[2] };
24 return static_cast<float>(std::sqrt(vd[0] * vd[0] + vd[1] * vd[1] + vd[2] * vd[2]));
25 }
26
27 template<int n>
Dot(const float * a,const float * b)28 float Dot(const float* a, const float* b)
29 {
30 double total = 0.0;
31 for (int i = 0; i < n; ++i) {
32 total += a[i] * b[i];
33 }
34 return static_cast<float>(total);
35 }
36
37 template<int n>
Combine(float * out,const float * a,const float * b,double scaleA,double scaleB)38 void Combine(float* out, const float* a, const float* b, double scaleA, double scaleB)
39 {
40 for (int i = 0; i < n; ++i) {
41 out[i] = static_cast<float>(a[i] * scaleA + b[i] * scaleB);
42 }
43 }
44
Cross3(float out[3],const float a[3],const float b[3])45 void Cross3(float out[3], const float a[3], const float b[3])
46 {
47 float x = a[1] * b[2] - a[2] * b[1];
48 float y = a[2] * b[0] - a[0] * b[2];
49 float z = a[0] * b[1] - a[1] * b[0];
50 out[0] = x;
51 out[1] = y;
52 out[2] = z;
53 }
54
55 // Returns false if the matrix cannot be normalized.
Normalize(Matrix4 & m)56 bool Normalize(Matrix4& m)
57 {
58 if (NearZero(m.Get(3, 3))) {
59 return false;
60 }
61 float scale = 1.0f / m.Get(3, 3);
62 for (int i = 0; i < 4; i++) {
63 for (int j = 0; j < 4; j++) {
64 auto value = m.Get(i, j) * scale;
65 m.Set(i, j, value);
66 }
67 }
68 return true;
69 }
70
BuildPerspectiveMatrix(const DecomposedTransform & decomp)71 Matrix4 BuildPerspectiveMatrix(const DecomposedTransform& decomp)
72 {
73 Matrix4 matrix = Matrix4::CreateIdentity();
74
75 for (int i = 0; i < 4; i++) {
76 matrix.Set(3, i, decomp.perspective[i]);
77 }
78 return matrix;
79 }
80
BuildTranslationMatrix(const DecomposedTransform & decomp)81 Matrix4 BuildTranslationMatrix(const DecomposedTransform& decomp)
82 {
83 Matrix4 matrix = Matrix4::CreateIdentity();
84 float dx = decomp.translate[0];
85 float dy = decomp.translate[1];
86 float dz = decomp.translate[2];
87 if (NearZero(dx) && NearZero(dy) && NearZero(dz)) {
88 return matrix;
89 }
90
91 matrix.Set(0, 3, dx);
92 matrix.Set(1, 3, dy);
93 matrix.Set(2, 3, dz);
94 return matrix;
95 }
96
BuildRotationMatrix(const DecomposedTransform & decomp)97 Matrix4 BuildRotationMatrix(const DecomposedTransform& decomp)
98 {
99 Matrix4 matrix4;
100 double x = decomp.quaternion.GetX();
101 double y = decomp.quaternion.GetY();
102 double z = decomp.quaternion.GetZ();
103 double w = decomp.quaternion.GetW();
104
105 matrix4.Set(0, 0, static_cast<float>(1.0 - 2.0 * (y * y + z * z)));
106 matrix4.Set(1, 0, static_cast<float>(2.0 * (x * y + z * w)));
107 matrix4.Set(2, 0, static_cast<float>(2.0 * (x * z - y * w)));
108 matrix4.Set(3, 0, 0);
109
110 matrix4.Set(0, 1, static_cast<float>(2.0 * (x * y - z * w)));
111 matrix4.Set(1, 1, static_cast<float>(1.0 - 2.0 * (x * x + z * z)));
112 matrix4.Set(2, 1, static_cast<float>(2.0 * (y * z + x * w)));
113 matrix4.Set(3, 1, 0);
114
115 matrix4.Set(0, 2, static_cast<float>(2.0 * (x * z + y * w)));
116 matrix4.Set(1, 2, static_cast<float>(2.0 * (y * z - x * w)));
117 matrix4.Set(2, 2, static_cast<float>(1.0 - 2.0 * (x * x + y * y)));
118 matrix4.Set(3, 2, 0);
119
120 matrix4.Set(0, 3, 0);
121 matrix4.Set(1, 3, 0);
122 matrix4.Set(2, 3, 0);
123 matrix4.Set(3, 3, 1);
124
125 return matrix4;
126 }
127
BuildSkewMatrix(const DecomposedTransform & decomp)128 Matrix4 BuildSkewMatrix(const DecomposedTransform& decomp)
129 {
130 Matrix4 matrix = Matrix4::CreateIdentity();
131
132 Matrix4 temp = Matrix4::CreateIdentity();
133 if (decomp.skew[2]) {
134 temp.Set(1, 2, decomp.skew[2]);
135 matrix = matrix * temp;
136 }
137
138 if (decomp.skew[1]) {
139 temp.Set(1, 2, 0);
140 temp.Set(0, 2, decomp.skew[1]);
141 matrix = matrix * temp;
142 }
143
144 if (decomp.skew[0]) {
145 temp.Set(0, 2, 0);
146 temp.Set(0, 1, decomp.skew[0]);
147 matrix = matrix * temp;
148 }
149 return matrix;
150 }
151
BuildScaleMatrix(const DecomposedTransform & decomp)152 Matrix4 BuildScaleMatrix(const DecomposedTransform& decomp)
153 {
154 Matrix4 matrix = Matrix4::CreateIdentity();
155 matrix.SetScale(decomp.scale[0], decomp.scale[1], decomp.scale[2]);
156 return matrix;
157 }
158
ComposeTransform(const Matrix4 & perspective,const Matrix4 & translation,const Matrix4 & rotation,const Matrix4 & skew,const Matrix4 & scale)159 Matrix4 ComposeTransform(const Matrix4& perspective, const Matrix4& translation, const Matrix4& rotation,
160 const Matrix4& skew, const Matrix4& scale)
161 {
162 Matrix4 matrix = Matrix4::CreateIdentity();
163 matrix = matrix * perspective;
164 matrix = matrix * translation;
165 matrix = matrix * rotation;
166 matrix = matrix * skew;
167 matrix = matrix * scale;
168 return matrix;
169 }
170
171 } // namespace
172
Blend(const TranslateOperation & to,const TranslateOperation & from,float progress)173 TranslateOperation TranslateOperation::Blend(
174 const TranslateOperation& to, const TranslateOperation& from, float progress)
175 {
176 TranslateOperation ret;
177 float scaleA = progress;
178 float scaleB = 1 - progress;
179 ret.dx = to.dx * scaleA + from.dx * scaleB;
180 ret.dy = to.dy * scaleA + from.dy * scaleB;
181 ret.dz = to.dz * scaleA + from.dz * scaleB;
182
183 return ret;
184 }
185
Blend(const ScaleOperation & to,const ScaleOperation & from,float progress)186 ScaleOperation ScaleOperation::Blend(const ScaleOperation& to, const ScaleOperation& from, float progress)
187 {
188 ScaleOperation ret;
189 float scaleA = progress;
190 float scaleB = 1 - progress;
191 ret.scaleX = to.scaleX * scaleA + from.scaleX * scaleB;
192 ret.scaleY = to.scaleY * scaleA + from.scaleY * scaleB;
193 ret.scaleZ = to.scaleZ * scaleA + from.scaleZ * scaleB;
194 return ret;
195 }
196
Blend(const SkewOperation & to,const SkewOperation & from,float progress)197 SkewOperation SkewOperation::Blend(const SkewOperation& to, const SkewOperation& from, float progress)
198 {
199 SkewOperation ret;
200 float scaleA = progress;
201 float scaleB = 1 - progress;
202 ret.skewX = to.skewX * scaleA + from.skewX * scaleB;
203 ret.skewY = to.skewY * scaleA + from.skewY * scaleB;
204 return ret;
205 }
206
Blend(const RotateOperation & to,const RotateOperation & from,float progress)207 RotateOperation RotateOperation::Blend(const RotateOperation& to, const RotateOperation& from, float progress)
208 {
209 RotateOperation ret;
210 float scaleA = progress;
211 float scaleB = 1 - progress;
212 ret.angle = to.angle * scaleA + from.angle * scaleB;
213 ret.dx = to.dx;
214 ret.dy = to.dy;
215 ret.dz = to.dz;
216 // rotate vector is (0,0,0) is error
217 if (NearZero(ret.dx) && NearZero(ret.dy) && NearZero(ret.dz)) {
218 ret.dx = from.dx;
219 ret.dy = from.dy;
220 ret.dz = from.dz;
221 }
222 return ret;
223 }
224
Blend(const PerspectiveOperation & to,const PerspectiveOperation & from,float progress)225 PerspectiveOperation PerspectiveOperation::Blend(
226 const PerspectiveOperation& to, const PerspectiveOperation& from, float progress)
227 {
228 PerspectiveOperation ret;
229 ret.distance = from.distance + (to.distance - from.distance) * progress;
230 return ret;
231 }
232
Blend(const TransformOperation & to,const TransformOperation & from,float progress)233 TransformOperation TransformOperation::Blend(
234 const TransformOperation& to, const TransformOperation& from, float progress)
235 {
236 TransformOperation ret;
237 if (to.type_ == from.type_ && to.type_ == TransformOperationType::UNDEFINED) {
238 return ret;
239 } else if (to.type_ == TransformOperationType::UNDEFINED) {
240 ret.type_ = from.type_;
241 BlendInner(Create(ret.type_), from, progress, ret);
242 } else if (from.type_ == TransformOperationType::UNDEFINED) {
243 ret.type_ = to.type_;
244 BlendInner(to, Create(ret.type_), progress, ret);
245 } else if (to.type_ == from.type_) {
246 ret.type_ = to.type_;
247 BlendInner(to, from, progress, ret);
248 }
249 return ret;
250 }
251
Create(TransformOperationType type)252 TransformOperation TransformOperation::Create(TransformOperationType type)
253 {
254 TransformOperation ret;
255 ret.type_ = type;
256 switch (ret.type_) {
257 case TransformOperationType::TRANSLATE:
258 ret.translateOperation_ = TranslateOperation();
259 break;
260 case TransformOperationType::SCALE:
261 ret.scaleOperation_ = ScaleOperation();
262 break;
263 case TransformOperationType::SKEW:
264 ret.skewOperation_ = SkewOperation();
265 break;
266 case TransformOperationType::ROTATE:
267 ret.rotateOperation_ = RotateOperation();
268 break;
269 case TransformOperationType::MATRIX:
270 ret.matrix4_ = Matrix4::CreateIdentity();
271 break;
272 case TransformOperationType::PERSPECTIVE:
273 ret.perspectiveOperation_ = PerspectiveOperation();
274 break;
275 case TransformOperationType::UNDEFINED:
276 break;
277 default:
278 break;
279 }
280 return ret;
281 }
282
BlendInner(const TransformOperation & to,const TransformOperation & from,float progress,TransformOperation & ret)283 void TransformOperation::BlendInner(
284 const TransformOperation& to, const TransformOperation& from, float progress, TransformOperation& ret)
285 {
286 switch (ret.type_) {
287 case TransformOperationType::TRANSLATE:
288 ret.translateOperation_ =
289 TranslateOperation::Blend(to.translateOperation_, from.translateOperation_, progress);
290 break;
291 case TransformOperationType::SCALE:
292 ret.scaleOperation_ = ScaleOperation::Blend(to.scaleOperation_, from.scaleOperation_, progress);
293 break;
294 case TransformOperationType::SKEW:
295 ret.skewOperation_ = SkewOperation::Blend(to.skewOperation_, from.skewOperation_, progress);
296 break;
297 case TransformOperationType::ROTATE:
298 ret.rotateOperation_ = RotateOperation::Blend(to.rotateOperation_, from.rotateOperation_, progress);
299 break;
300 case TransformOperationType::MATRIX: {
301 DecomposedTransform toTransform;
302 DecomposedTransform fromTransform;
303 if (TransformUtil::DecomposeTransform(toTransform, to.matrix4_) &&
304 TransformUtil::DecomposeTransform(fromTransform, from.matrix4_)) {
305 auto result = TransformUtil::BlendDecomposedTransforms(toTransform, fromTransform, progress);
306 ret.matrix4_ = TransformUtil::ComposeTransform(result);
307 } else {
308 LOGE("DecomposeTransform failed");
309 }
310 break;
311 }
312 case TransformOperationType::PERSPECTIVE:
313 ret.perspectiveOperation_ =
314 PerspectiveOperation::Blend(to.perspectiveOperation_, from.perspectiveOperation_, progress);
315 break;
316 case TransformOperationType::UNDEFINED:
317 break;
318 default:
319 break;
320 }
321 }
322
ToString() const323 std::string DecomposedTransform::ToString() const
324 {
325 std::string out;
326 out.append("translate: ")
327 .append(std::to_string(translate[0]))
328 .append(" ")
329 .append(std::to_string(translate[1]))
330 .append(" ")
331 .append(std::to_string(translate[2]))
332 .append("\n")
333 .append("scale: ")
334 .append(std::to_string(scale[0]))
335 .append(" ")
336 .append(std::to_string(scale[1]))
337 .append(" ")
338 .append(std::to_string(scale[2]))
339 .append("\n")
340 .append("skew: ")
341 .append(std::to_string(skew[0]))
342 .append(" ")
343 .append(std::to_string(skew[1]))
344 .append(" ")
345 .append(std::to_string(skew[2]))
346 .append("\n")
347 .append("perspective: ")
348 .append(std::to_string(perspective[0]))
349 .append(" ")
350 .append(std::to_string(perspective[1]))
351 .append(" ")
352 .append(std::to_string(perspective[2]))
353 .append(" ")
354 .append(std::to_string(perspective[3]))
355 .append("\n")
356 .append("quaternion: ")
357 .append(std::to_string(quaternion.GetX()))
358 .append(" ")
359 .append(std::to_string(quaternion.GetY()))
360 .append(" ")
361 .append(std::to_string(quaternion.GetZ()))
362 .append(" ")
363 .append(std::to_string(quaternion.GetW()))
364 .append("\n");
365 return out;
366 }
367
Blend(const TransformOperations & to,const TransformOperations & from,float progress)368 TransformOperations TransformOperations::Blend(
369 const TransformOperations& to, const TransformOperations& from, float progress)
370 {
371 TransformOperations result;
372 to.BlendInner(from, progress, result);
373 return result;
374 }
375
MatchingLength(const TransformOperations & to,const TransformOperations & from) const376 std::size_t TransformOperations::MatchingLength(const TransformOperations& to, const TransformOperations& from) const
377 {
378 auto numOperations = std::min(to.operations_.size(), from.operations_.size());
379
380 for (std::size_t i = 0; i < numOperations; i++) {
381 auto& first = to.operations_[i];
382 auto& second = from.operations_[i];
383
384 if (first.type_ != TransformOperationType::UNDEFINED || second.type_ != TransformOperationType::UNDEFINED) {
385 if (first.type_ != second.type_) {
386 return i;
387 }
388 }
389 }
390 return std::max(to.operations_.size(), from.operations_.size());
391 }
392
ParseOperationsToMatrix(std::vector<TransformOperation> & operations)393 void TransformOperations::ParseOperationsToMatrix(std::vector<TransformOperation>& operations)
394 {
395 for (auto& operation : operations) {
396 ParseOperationToMatrix(operation);
397 }
398 }
399
ParseOperationToMatrix(TransformOperation & operation)400 void TransformOperations::ParseOperationToMatrix(TransformOperation& operation)
401 {
402 switch (operation.type_) {
403 case TransformOperationType::TRANSLATE: {
404 auto& translate = operation.translateOperation_;
405 float dx = translate.dx.Value();
406 float dy = translate.dy.Value();
407 float dz = translate.dz.Value();
408 operation.matrix4_ = Matrix4::CreateTranslate(dx, dy, dz);
409 break;
410 }
411 case TransformOperationType::SCALE: {
412 auto& scale = operation.scaleOperation_;
413 operation.matrix4_ = Matrix4::CreateScale(scale.scaleX, scale.scaleY, scale.scaleZ);
414 break;
415 }
416 case TransformOperationType::SKEW: {
417 auto& skew = operation.skewOperation_;
418 operation.matrix4_ = Matrix4::CreateSkew(skew.skewX, skew.skewY);
419 break;
420 }
421 case TransformOperationType::ROTATE: {
422 auto& rotate = operation.rotateOperation_;
423 operation.matrix4_ = Matrix4::CreateRotate(rotate.angle, rotate.dx, rotate.dy, rotate.dz);
424 break;
425 }
426 case TransformOperationType::PERSPECTIVE: {
427 auto& perspective = operation.perspectiveOperation_;
428 double distance = perspective.distance.Value();
429 operation.matrix4_ = Matrix4::CreatePerspective(distance);
430 break;
431 }
432 case TransformOperationType::MATRIX:
433 case TransformOperationType::UNDEFINED:
434 break;
435 }
436 }
437
BlendInner(const TransformOperations & from,float progress,TransformOperations & out) const438 void TransformOperations::BlendInner(const TransformOperations& from, float progress, TransformOperations& out) const
439 {
440 auto matchPrefix = MatchingLength(*this, from);
441 auto fromSize = from.operations_.size();
442 auto toSize = operations_.size();
443
444 // find most match type transform
445 for (std::size_t i = 0; i < matchPrefix; i++) {
446 const auto& fromTransformOperation = i >= fromSize ? TransformOperation() : from.operations_[i];
447 const auto& toTransformOperation = i >= toSize ? TransformOperation() : operations_[i];
448 out.operations_.push_back(TransformOperation::Blend(toTransformOperation, fromTransformOperation, progress));
449 }
450 // type not match
451 if (matchPrefix < std::max(fromSize, toSize)) {
452 TransformOperation fromTransformOperation;
453 fromTransformOperation.type_ = TransformOperationType::MATRIX;
454 fromTransformOperation.matrix4_ = from.ComputerRemaining(matchPrefix);
455 TransformOperation toTransformOperation;
456 toTransformOperation.type_ = TransformOperationType::MATRIX;
457 toTransformOperation.matrix4_ = ComputerRemaining(matchPrefix);
458 out.operations_.push_back(TransformOperation::Blend(toTransformOperation, fromTransformOperation, progress));
459 }
460 }
461
ComputerRemaining(std::size_t startOffset) const462 Matrix4 TransformOperations::ComputerRemaining(std::size_t startOffset) const
463 {
464 Matrix4 result = Matrix4::CreateIdentity();
465 for (auto i = startOffset; i < operations_.size(); i++) {
466 result = result * operations_[i].matrix4_;
467 }
468 return result;
469 }
470
BlendDecomposedTransforms(const DecomposedTransform & to,const DecomposedTransform & from,double progress)471 DecomposedTransform TransformUtil::BlendDecomposedTransforms(
472 const DecomposedTransform& to, const DecomposedTransform& from, double progress)
473 {
474 DecomposedTransform ret;
475 Combine<3>(ret.translate, to.translate, from.translate, progress, 1.0 - progress);
476 Combine<3>(ret.scale, to.scale, from.scale, progress, 1.0 - progress);
477 Combine<3>(ret.skew, to.skew, from.skew, progress, 1.0 - progress);
478 Combine<4>(ret.perspective, to.perspective, from.perspective, progress, 1.0 - progress);
479 ret.quaternion = from.quaternion.Slerp(to.quaternion, progress);
480 return ret;
481 }
482
DecomposeTransform(DecomposedTransform & out,const Matrix4 & transform)483 bool TransformUtil::DecomposeTransform(DecomposedTransform& out, const Matrix4& transform)
484 {
485 Matrix4 matrix = transform;
486
487 if (!Normalize(matrix)) {
488 return false;
489 }
490
491 Matrix4 perspectiveMatrix = matrix;
492 for (int i = 0; i < 3; i++) {
493 perspectiveMatrix.Set(3, i, 0.0);
494 }
495 perspectiveMatrix.Set(3, 3, 1.0);
496
497 if (NearZero(std::abs(perspectiveMatrix.Determinant()))) {
498 return false;
499 }
500
501 if (!NearZero(matrix.Get(3, 0)) || !NearZero(matrix.Get(3, 1)) || !NearZero(matrix.Get(3, 2))) {
502 double rhs[4] = { matrix.Get(3, 0), matrix.Get(3, 1), matrix.Get(3, 2), matrix.Get(3, 3) };
503
504 Matrix4 inversePerspectiveMatrix = Matrix4::Invert(perspectiveMatrix);
505 Matrix4 transposedInversePerspectiveMatrix = inversePerspectiveMatrix;
506
507 transposedInversePerspectiveMatrix.Transpose();
508 transposedInversePerspectiveMatrix.MapScalars(rhs, 4);
509
510 for (int32_t i = 0; i < 4; i++) {
511 out.perspective[i] = rhs[i];
512 }
513 } else {
514 // No perspective.
515 for (int i = 0; i < 3; ++i)
516 out.perspective[i] = 0.0;
517 out.perspective[3] = 1.0;
518 }
519
520 for (int32_t i = 0; i < 3; i++) {
521 out.translate[i] = matrix.Get(i, 3);
522 }
523
524 // Copy of matrix is stored in column major order to facilitate column-level
525 // operations.
526 float column[3][3];
527 for (int32_t i = 0; i < 3; i++) {
528 for (int32_t j = 0; j < 3; j++) {
529 column[i][j] = matrix.Get(j, i);
530 }
531 }
532
533 // Compute X scale factor and normalize first column.
534 out.scale[0] = Length3(column[0]);
535 if (out.scale[0] != 0.0) {
536 column[0][0] /= out.scale[0];
537 column[0][1] /= out.scale[0];
538 column[0][2] /= out.scale[0];
539 }
540
541 // Compute XY shear factor and make 2nd column orthogonal to 1st.
542 out.skew[0] = Dot<3>(column[0], column[1]);
543 Combine<3>(column[1], column[1], column[0], 1.0, -out.skew[0]);
544
545 // Now, compute Y scale and normalize 2nd column.
546 out.scale[1] = Length3(column[1]);
547 if (out.scale[1] != 0.0) {
548 column[1][0] /= out.scale[1];
549 column[1][1] /= out.scale[1];
550 column[1][2] /= out.scale[1];
551 }
552
553 out.skew[0] /= out.scale[1];
554
555 // Compute XZ and YZ shears, orthogonalize the 3rd column.
556 out.skew[1] = Dot<3>(column[0], column[2]);
557 Combine<3>(column[2], column[2], column[0], 1.0, -out.skew[1]);
558 out.skew[2] = Dot<3>(column[1], column[2]);
559 Combine<3>(column[2], column[2], column[1], 1.0, -out.skew[2]);
560
561 // Next, get Z scale and normalize the 3rd column.
562 out.scale[2] = Length3(column[2]);
563 if (out.scale[2] != 0.0) {
564 column[2][0] /= out.scale[2];
565 column[2][1] /= out.scale[2];
566 column[2][2] /= out.scale[2];
567 }
568
569 out.skew[1] /= out.scale[2];
570 out.skew[2] /= out.scale[2];
571
572 // At this point, the matrix is orthonormal.
573 // Check for a coordinate system flip. If the determinant
574 // is -1, then negate the matrix and the scaling factors.
575 // only 1 axis is flipped when the determinant is negative. Verify if it is
576 // correct to flip all of the scales and matrix elements, as this introduces
577 // rotation for the simple case of a single axis scale inversion.
578 float pdum3[3];
579 Cross3(pdum3, column[1], column[2]);
580 if (Dot<3>(column[0], pdum3) < 0) {
581 for (int i = 0; i < 3; i++) {
582 out.scale[i] *= -1.0;
583 for (int j = 0; j < 3; ++j)
584 column[i][j] *= -1.0;
585 }
586 }
587
588 // See https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion.
589 // Note: deviating from spec (http://www.w3.org/TR/css3-transforms/)
590 // which has a degenerate case of zero off-diagonal elements in the
591 // orthonormal matrix, which leads to errors in determining the sign
592 // of the quaternions.
593 double q_xx = column[0][0];
594 double q_xy = column[1][0];
595 double q_xz = column[2][0];
596 double q_yx = column[0][1];
597 double q_yy = column[1][1];
598 double q_yz = column[2][1];
599 double q_zx = column[0][2];
600 double q_zy = column[1][2];
601 double q_zz = column[2][2];
602
603 double r, s, t, x, y, z, w;
604 t = q_xx + q_yy + q_zz;
605 if (t > 0) {
606 r = std::sqrt(1.0 + t);
607 s = 0.5 / r;
608 w = 0.5 * r;
609 x = (q_zy - q_yz) * s;
610 y = (q_xz - q_zx) * s;
611 z = (q_yx - q_xy) * s;
612 } else if (q_xx > q_yy && q_xx > q_zz) {
613 r = std::sqrt(1.0 + q_xx - q_yy - q_zz);
614 s = 0.5 / r;
615 x = 0.5 * r;
616 y = (q_xy + q_yx) * s;
617 z = (q_xz + q_zx) * s;
618 w = (q_zy - q_yz) * s;
619 } else if (q_yy > q_zz) {
620 r = std::sqrt(1.0 - q_xx + q_yy - q_zz);
621 s = 0.5 / r;
622 x = (q_xy + q_yx) * s;
623 y = 0.5 * r;
624 z = (q_yz + q_zy) * s;
625 w = (q_xz - q_zx) * s;
626 } else {
627 r = std::sqrt(1.0 - q_xx - q_yy + q_zz);
628 s = 0.5 / r;
629 x = (q_xz + q_zx) * s;
630 y = (q_yz + q_zy) * s;
631 z = 0.5 * r;
632 w = (q_yx - q_xy) * s;
633 }
634
635 out.quaternion.SetX(static_cast<float>(x));
636 out.quaternion.SetY(static_cast<float>(y));
637 out.quaternion.SetZ(static_cast<float>(z));
638 out.quaternion.SetW(static_cast<float>(w));
639
640 return true;
641 }
642
ComposeTransform(const struct DecomposedTransform & decomp)643 Matrix4 TransformUtil::ComposeTransform(const struct DecomposedTransform& decomp)
644 {
645 Matrix4 perspective = BuildPerspectiveMatrix(decomp);
646 Matrix4 translation = BuildTranslationMatrix(decomp);
647 Matrix4 rotation = BuildRotationMatrix(decomp);
648 Matrix4 skew = BuildSkewMatrix(decomp);
649 Matrix4 scale = BuildScaleMatrix(decomp);
650
651 return OHOS::Ace::ComposeTransform(perspective, translation, rotation, skew, scale);
652 }
653
654 } // namespace OHOS::Ace