gecko-dev/dom/vr/XRRigidTransform.cpp

188 строки
6.2 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/XRRigidTransform.h"
#include "mozilla/dom/DOMPoint.h"
#include "mozilla/dom/Pose.h"
#include "mozilla/dom/DOMPointBinding.h"
#include "mozilla/HoldDropJSObjects.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(XRRigidTransform)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XRRigidTransform)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent, mPosition, mOrientation, mInverse)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->mMatrixArray = nullptr;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XRRigidTransform)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent, mPosition, mOrientation, mInverse)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(XRRigidTransform)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMatrixArray)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(XRRigidTransform, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(XRRigidTransform, Release)
XRRigidTransform::XRRigidTransform(nsISupports* aParent,
const gfx::PointDouble3D& aPosition,
const gfx::QuaternionDouble& aOrientation)
: mParent(aParent),
mMatrixArray(nullptr),
mPosition(nullptr),
mOrientation(nullptr),
mInverse(nullptr),
mRawPosition(aPosition),
mRawOrientation(aOrientation),
mNeedsUpdate(true) {
mozilla::HoldJSObjects(this);
mRawTransformMatrix.SetRotationFromQuaternion(mRawOrientation);
mRawTransformMatrix.PostTranslate(mRawPosition);
}
XRRigidTransform::XRRigidTransform(nsISupports* aParent,
const gfx::Matrix4x4Double& aTransform)
: mParent(aParent),
mMatrixArray(nullptr),
mPosition(nullptr),
mOrientation(nullptr),
mInverse(nullptr),
mNeedsUpdate(true) {
mozilla::HoldJSObjects(this);
gfx::PointDouble3D scale;
mRawTransformMatrix = aTransform;
mRawTransformMatrix.Decompose(mRawPosition, mRawOrientation, scale);
}
XRRigidTransform::~XRRigidTransform() { mozilla::DropJSObjects(this); }
/* static */ already_AddRefed<XRRigidTransform> XRRigidTransform::Constructor(
const GlobalObject& aGlobal, const DOMPointInit& aOrigin,
const DOMPointInit& aDirection, ErrorResult& aRv) {
gfx::PointDouble3D position(aOrigin.mX, aOrigin.mY, aOrigin.mZ);
gfx::QuaternionDouble orientation(aDirection.mX, aDirection.mY, aDirection.mZ,
aDirection.mW);
orientation.Normalize();
RefPtr<XRRigidTransform> obj =
new XRRigidTransform(aGlobal.GetAsSupports(), position, orientation);
return obj.forget();
}
JSObject* XRRigidTransform::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
return XRRigidTransform_Binding::Wrap(aCx, this, aGivenProto);
}
DOMPoint* XRRigidTransform::Position() {
if (!mPosition) {
mPosition = new DOMPoint(mParent, mRawPosition.x, mRawPosition.y,
mRawPosition.z, 1.0f);
}
return mPosition;
}
DOMPoint* XRRigidTransform::Orientation() {
if (!mOrientation) {
mOrientation = new DOMPoint(mParent, mRawOrientation.x, mRawOrientation.y,
mRawOrientation.z, mRawOrientation.w);
}
return mOrientation;
}
XRRigidTransform& XRRigidTransform::operator=(const XRRigidTransform& aOther) {
Update(aOther.mRawPosition, aOther.mRawOrientation);
return *this;
}
gfx::QuaternionDouble XRRigidTransform::RawOrientation() const {
return mRawOrientation;
}
gfx::PointDouble3D XRRigidTransform::RawPosition() const {
return mRawPosition;
}
void XRRigidTransform::Update(const gfx::PointDouble3D& aPosition,
const gfx::QuaternionDouble& aOrientation) {
mNeedsUpdate = true;
mRawPosition = aPosition;
mRawOrientation = aOrientation;
mRawTransformMatrix.SetRotationFromQuaternion(mRawOrientation);
mRawTransformMatrix.PostTranslate(mRawPosition);
UpdateInternal();
}
void XRRigidTransform::Update(const gfx::Matrix4x4Double& aTransform) {
mNeedsUpdate = true;
mRawTransformMatrix = aTransform;
gfx::PointDouble3D scale;
mRawTransformMatrix.Decompose(mRawPosition, mRawOrientation, scale);
UpdateInternal();
}
void XRRigidTransform::UpdateInternal() {
if (mPosition) {
mPosition->SetX(mRawPosition.x);
mPosition->SetY(mRawPosition.y);
mPosition->SetZ(mRawPosition.z);
}
if (mOrientation) {
mOrientation->SetX(mRawOrientation.x);
mOrientation->SetY(mRawOrientation.y);
mOrientation->SetZ(mRawOrientation.z);
mOrientation->SetW(mRawOrientation.w);
}
if (mInverse) {
gfx::Matrix4x4Double inverseMatrix = mRawTransformMatrix;
Unused << inverseMatrix.Invert();
mInverse->Update(inverseMatrix);
}
}
void XRRigidTransform::GetMatrix(JSContext* aCx,
JS::MutableHandle<JSObject*> aRetval,
ErrorResult& aRv) {
if (!mMatrixArray || mNeedsUpdate) {
mNeedsUpdate = false;
const uint32_t size = 16;
float components[size] = {};
// In order to avoid some platforms which only copy
// the first or last two bytes of a Float64 to a Float32.
for (uint32_t i = 0; i < size; ++i) {
components[i] = mRawTransformMatrix.components[i];
}
Pose::SetFloat32Array(aCx, this, aRetval, mMatrixArray, components, 16,
aRv);
if (!mMatrixArray) {
return;
}
}
if (mMatrixArray) {
JS::ExposeObjectToActiveJS(mMatrixArray);
}
aRetval.set(mMatrixArray);
}
already_AddRefed<XRRigidTransform> XRRigidTransform::Inverse() {
if (!mInverse) {
gfx::Matrix4x4Double inverseMatrix = mRawTransformMatrix;
Unused << inverseMatrix.Invert();
mInverse = new XRRigidTransform(mParent, inverseMatrix);
}
RefPtr<XRRigidTransform> inverse = mInverse;
return inverse.forget();
}
} // namespace dom
} // namespace mozilla