XRRigidTransform.cpp (5826B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/XRRigidTransform.h" 8 9 #include "mozilla/HoldDropJSObjects.h" 10 #include "mozilla/dom/DOMPoint.h" 11 #include "mozilla/dom/DOMPointBinding.h" 12 #include "mozilla/dom/Pose.h" 13 #include "nsWrapperCache.h" 14 15 namespace mozilla::dom { 16 17 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_WITH_JS_MEMBERS(XRRigidTransform, 18 (mParent, mPosition, 19 mOrientation, mInverse), 20 (mMatrixArray)) 21 22 XRRigidTransform::XRRigidTransform(nsISupports* aParent, 23 const gfx::PointDouble3D& aPosition, 24 const gfx::QuaternionDouble& aOrientation) 25 : mParent(aParent), 26 mMatrixArray(nullptr), 27 mPosition(nullptr), 28 mOrientation(nullptr), 29 mInverse(nullptr), 30 mRawPosition(aPosition), 31 mRawOrientation(aOrientation), 32 mNeedsUpdate(true) { 33 mozilla::HoldJSObjects(this); 34 mRawTransformMatrix.SetRotationFromQuaternion(mRawOrientation); 35 mRawTransformMatrix.PostTranslate(mRawPosition); 36 } 37 38 XRRigidTransform::XRRigidTransform(nsISupports* aParent, 39 const gfx::Matrix4x4Double& aTransform) 40 : mParent(aParent), 41 mMatrixArray(nullptr), 42 mPosition(nullptr), 43 mOrientation(nullptr), 44 mInverse(nullptr), 45 mNeedsUpdate(true) { 46 mozilla::HoldJSObjects(this); 47 gfx::PointDouble3D scale; 48 mRawTransformMatrix = aTransform; 49 mRawTransformMatrix.Decompose(mRawPosition, mRawOrientation, scale); 50 } 51 52 XRRigidTransform::~XRRigidTransform() { mozilla::DropJSObjects(this); } 53 54 /* static */ already_AddRefed<XRRigidTransform> XRRigidTransform::Constructor( 55 const GlobalObject& aGlobal, const DOMPointInit& aOrigin, 56 const DOMPointInit& aDirection, ErrorResult& aRv) { 57 gfx::PointDouble3D position(aOrigin.mX, aOrigin.mY, aOrigin.mZ); 58 gfx::QuaternionDouble orientation(aDirection.mX, aDirection.mY, aDirection.mZ, 59 aDirection.mW); 60 orientation.Normalize(); 61 RefPtr<XRRigidTransform> obj = 62 new XRRigidTransform(aGlobal.GetAsSupports(), position, orientation); 63 return obj.forget(); 64 } 65 66 JSObject* XRRigidTransform::WrapObject(JSContext* aCx, 67 JS::Handle<JSObject*> aGivenProto) { 68 return XRRigidTransform_Binding::Wrap(aCx, this, aGivenProto); 69 } 70 71 DOMPoint* XRRigidTransform::Position() { 72 if (!mPosition) { 73 mPosition = new DOMPoint(mParent, mRawPosition.x, mRawPosition.y, 74 mRawPosition.z, 1.0f); 75 } 76 return mPosition; 77 } 78 79 DOMPoint* XRRigidTransform::Orientation() { 80 if (!mOrientation) { 81 mOrientation = new DOMPoint(mParent, mRawOrientation.x, mRawOrientation.y, 82 mRawOrientation.z, mRawOrientation.w); 83 } 84 return mOrientation; 85 } 86 87 XRRigidTransform& XRRigidTransform::operator=(const XRRigidTransform& aOther) { 88 Update(aOther.mRawPosition, aOther.mRawOrientation); 89 return *this; 90 } 91 92 gfx::QuaternionDouble XRRigidTransform::RawOrientation() const { 93 return mRawOrientation; 94 } 95 gfx::PointDouble3D XRRigidTransform::RawPosition() const { 96 return mRawPosition; 97 } 98 99 void XRRigidTransform::Update(const gfx::PointDouble3D& aPosition, 100 const gfx::QuaternionDouble& aOrientation) { 101 mNeedsUpdate = true; 102 mRawPosition = aPosition; 103 mRawOrientation = aOrientation; 104 mRawTransformMatrix.SetRotationFromQuaternion(mRawOrientation); 105 mRawTransformMatrix.PostTranslate(mRawPosition); 106 UpdateInternal(); 107 } 108 109 void XRRigidTransform::Update(const gfx::Matrix4x4Double& aTransform) { 110 mNeedsUpdate = true; 111 mRawTransformMatrix = aTransform; 112 gfx::PointDouble3D scale; 113 mRawTransformMatrix.Decompose(mRawPosition, mRawOrientation, scale); 114 UpdateInternal(); 115 } 116 117 void XRRigidTransform::UpdateInternal() { 118 if (mPosition) { 119 mPosition->SetX(mRawPosition.x); 120 mPosition->SetY(mRawPosition.y); 121 mPosition->SetZ(mRawPosition.z); 122 } 123 if (mOrientation) { 124 mOrientation->SetX(mRawOrientation.x); 125 mOrientation->SetY(mRawOrientation.y); 126 mOrientation->SetZ(mRawOrientation.z); 127 mOrientation->SetW(mRawOrientation.w); 128 } 129 if (mInverse) { 130 gfx::Matrix4x4Double inverseMatrix = mRawTransformMatrix; 131 (void)inverseMatrix.Invert(); 132 mInverse->Update(inverseMatrix); 133 } 134 } 135 136 void XRRigidTransform::GetMatrix(JSContext* aCx, 137 JS::MutableHandle<JSObject*> aRetval, 138 ErrorResult& aRv) { 139 if (!mMatrixArray || mNeedsUpdate) { 140 mNeedsUpdate = false; 141 142 const uint32_t size = 16; 143 float components[size] = {}; 144 // In order to avoid some platforms which only copy 145 // the first or last two bytes of a Float64 to a Float32. 146 for (uint32_t i = 0; i < size; ++i) { 147 components[i] = mRawTransformMatrix.components[i]; 148 } 149 Pose::SetFloat32Array(aCx, this, aRetval, mMatrixArray, components, 16, 150 aRv); 151 if (!mMatrixArray) { 152 return; 153 } 154 } 155 if (mMatrixArray) { 156 JS::ExposeObjectToActiveJS(mMatrixArray); 157 } 158 aRetval.set(mMatrixArray); 159 } 160 161 already_AddRefed<XRRigidTransform> XRRigidTransform::Inverse() { 162 if (!mInverse) { 163 gfx::Matrix4x4Double inverseMatrix = mRawTransformMatrix; 164 (void)inverseMatrix.Invert(); 165 mInverse = new XRRigidTransform(mParent, inverseMatrix); 166 } 167 168 RefPtr<XRRigidTransform> inverse = mInverse; 169 return inverse.forget(); 170 } 171 172 } // namespace mozilla::dom