blob: a4497bb10eccb4d578a5746078d7a41661843c7b [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/xr/xr_rigid_transform.h"
#include "third_party/blink/renderer/modules/xr/xr_utils.h"
namespace blink {
// makes a deep copy of transformationMatrix
XRRigidTransform::XRRigidTransform(
const TransformationMatrix& transformationMatrix)
: matrix_(TransformationMatrix::Create(transformationMatrix)) {
DecomposeMatrix();
}
// takes ownership of transformationMatrix instead of copying it
XRRigidTransform::XRRigidTransform(
std::unique_ptr<TransformationMatrix> transformationMatrix)
: matrix_(std::move(transformationMatrix)) {
DecomposeMatrix();
}
void XRRigidTransform::DecomposeMatrix() {
// decompose matrix to position and orientation
TransformationMatrix::DecomposedType decomposed;
bool succeeded = matrix_->Decompose(decomposed);
if (succeeded) {
position_ =
DOMPointReadOnly::Create(decomposed.translate_x, decomposed.translate_y,
decomposed.translate_z, 1.0);
orientation_ = makeNormalizedQuaternion(
decomposed.quaternion_x, decomposed.quaternion_y,
decomposed.quaternion_z, decomposed.quaternion_w);
} else {
// TODO: Is this the correct way to handle a failure here?
position_ = DOMPointReadOnly::Create(0.0, 0.0, 0.0, 1.0);
orientation_ = DOMPointReadOnly::Create(0.0, 0.0, 0.0, 1.0);
}
}
// deep copy
XRRigidTransform::XRRigidTransform(const XRRigidTransform& other) {
*this = other;
}
// deep copy
XRRigidTransform& XRRigidTransform::operator=(const XRRigidTransform& other) {
if (&other == this)
return *this;
position_ =
DOMPointReadOnly::Create(other.position_->x(), other.position_->y(),
other.position_->z(), other.position_->w());
orientation_ = DOMPointReadOnly::Create(
other.orientation_->x(), other.orientation_->y(), other.orientation_->z(),
other.orientation_->w());
if (other.matrix_) {
matrix_ = TransformationMatrix::Create(*(other.matrix_.get()));
}
return *this;
}
XRRigidTransform::XRRigidTransform(DOMPointInit* position,
DOMPointInit* orientation) {
if (position) {
position_ = DOMPointReadOnly::Create(position->x(), position->y(),
position->z(), 1.0);
} else {
position_ = DOMPointReadOnly::Create(0.0, 0.0, 0.0, 1.0);
}
if (orientation) {
orientation_ = makeNormalizedQuaternion(orientation->x(), orientation->y(),
orientation->z(), orientation->w());
} else {
orientation_ = DOMPointReadOnly::Create(0.0, 0.0, 0.0, 1.0);
}
// Computing transformation matrix from position and orientation is expensive,
// so compute it lazily in matrix().
}
XRRigidTransform* XRRigidTransform::Create(DOMPointInit* position,
DOMPointInit* orientation) {
return MakeGarbageCollected<XRRigidTransform>(position, orientation);
}
DOMFloat32Array* XRRigidTransform::matrix() {
EnsureMatrix();
return transformationMatrixToDOMFloat32Array(*matrix_);
}
TransformationMatrix XRRigidTransform::InverseMatrix() {
EnsureMatrix();
DCHECK(matrix_->IsInvertible());
return matrix_->Inverse();
}
void XRRigidTransform::EnsureMatrix() {
if (!matrix_) {
matrix_ = TransformationMatrix::Create();
TransformationMatrix::DecomposedType decomp;
memset(&decomp, 0, sizeof(decomp));
decomp.perspective_w = 1;
decomp.scale_x = 1;
decomp.scale_y = 1;
decomp.scale_z = 1;
decomp.quaternion_x = orientation_->x();
decomp.quaternion_y = orientation_->y();
decomp.quaternion_z = orientation_->z();
decomp.quaternion_w = orientation_->w();
decomp.translate_x = position_->x();
decomp.translate_y = position_->y();
decomp.translate_z = position_->z();
matrix_->Recompose(decomp);
}
}
void XRRigidTransform::Trace(blink::Visitor* visitor) {
visitor->Trace(position_);
visitor->Trace(orientation_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink