1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
// Copyright 2020 The Chromium Authors
// 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_hand.h"
#include <memory>
#include <utility>
#include "base/memory/raw_ref.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
#include "third_party/blink/renderer/modules/xr/xr_joint_space.h"
#include "third_party/blink/renderer/modules/xr/xr_utils.h"
namespace blink {
using XRJointVector = GCedHeapVector<Member<XRJointSpace>>;
class XRHandIterationSource final
: public PairSyncIterable<XRHand>::IterationSource {
public:
explicit XRHandIterationSource(const Member<XRJointVector>& joints,
XRHand* xr_hand)
: joints_(joints), xr_hand_(xr_hand) {}
bool FetchNextItem(ScriptState*,
V8XRHandJoint& key,
XRJointSpace*& value,
ExceptionState&) override {
if (index_ >= V8XRHandJoint::kEnumSize)
return false;
key = V8XRHandJoint(static_cast<V8XRHandJoint::Enum>(index_));
value = joints_->at(index_);
index_++;
return true;
}
void Trace(Visitor* visitor) const override {
visitor->Trace(joints_);
visitor->Trace(xr_hand_);
PairSyncIterable<XRHand>::IterationSource::Trace(visitor);
}
private:
wtf_size_t index_ = 0;
const Member<const XRJointVector> joints_;
Member<XRHand> xr_hand_; // Owner object of `joints_`
};
XRHand::XRHand(const device::mojom::blink::XRHandTrackingData* state,
XRInputSource* input_source)
: joints_(MakeGarbageCollected<XRJointVector>()) {
joints_->ReserveInitialCapacity(kNumJoints);
DCHECK_EQ(kNumJoints, V8XRHandJoint::kEnumSize);
for (unsigned i = 0; i < kNumJoints; ++i) {
device::mojom::blink::XRHandJoint joint =
static_cast<device::mojom::blink::XRHandJoint>(i);
DCHECK_EQ(MojomHandJointToV8Enum(joint),
static_cast<V8XRHandJoint::Enum>(i));
joints_->push_back(MakeGarbageCollected<XRJointSpace>(
this, input_source->session(), nullptr, joint, 0.0f,
input_source->xr_handedness()));
}
updateFromHandTrackingData(state, input_source);
}
XRJointSpace* XRHand::get(const V8XRHandJoint& key) const {
wtf_size_t index = static_cast<wtf_size_t>(key.AsEnum());
return joints_->at(index).Get();
}
void XRHand::updateFromHandTrackingData(
const device::mojom::blink::XRHandTrackingData* state,
XRInputSource* input_source) {
bool new_missing_poses = false; // hand was updated with a null pose
bool new_poses = false; // hand was updated with a valid pose
for (const auto& hand_joint : state->hand_joint_data) {
unsigned joint_index = static_cast<unsigned>(hand_joint->joint);
std::unique_ptr<gfx::Transform> mojo_from_joint = nullptr;
if (hand_joint->mojo_from_joint) {
new_poses = true;
mojo_from_joint =
std::make_unique<gfx::Transform>(*hand_joint->mojo_from_joint);
} else {
new_missing_poses = true;
}
joints_->at(joint_index)
->UpdateTracking(std::move(mojo_from_joint), hand_joint->radius);
}
if (new_missing_poses) {
// There is at least one missing pose.
has_missing_poses_ = true;
} else if (has_missing_poses_ && new_poses) {
// Need to check if there are any missing poses
has_missing_poses_ =
std::ranges::any_of(*joints_, [](const Member<XRJointSpace>& joint) {
return !joint->MojoFromNative().has_value();
});
}
}
XRHand::IterationSource* XRHand::CreateIterationSource(
ScriptState* script_state,
ExceptionState& exception_state) {
return MakeGarbageCollected<XRHandIterationSource>(joints_, this);
}
void XRHand::Trace(Visitor* visitor) const {
visitor->Trace(joints_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink
|