зеркало из https://github.com/mozilla/gecko-dev.git
188 строки
6.2 KiB
C++
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
|