blob: 0f7e47df622c31cbb195eecd0f105af1f44ac77d [file] [log] [blame]
// Copyright 2020 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_hand.h"
#include <memory>
#include <utility>
#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 {
class XRHandIterationSource final
: public PairIterable<String,
IDLString,
Member<XRJointSpace>,
XRJointSpace>::IterationSource {
public:
explicit XRHandIterationSource(HeapVector<Member<XRJointSpace>>& joints)
: index_(0), joints_(joints) {}
bool Next(ScriptState*,
String& key,
Member<XRJointSpace>& value,
ExceptionState&) override {
if (index_ >= joints_.size())
return false;
key = MojomHandJointToString(
static_cast<device::mojom::blink::XRHandJoint>(index_));
value = joints_.at(index_);
index_++;
return true;
}
void Trace(Visitor* visitor) const override {
PairIterable<String, IDLString, Member<XRJointSpace>,
XRJointSpace>::IterationSource::Trace(visitor);
}
private:
wtf_size_t index_;
const HeapVector<Member<XRJointSpace>>& joints_;
};
XRHand::XRHand(const device::mojom::blink::XRHandTrackingData* state,
XRInputSource* input_source)
: joints_(kNumJoints) {
for (unsigned i = 0; i < kNumJoints; ++i) {
device::mojom::blink::XRHandJoint joint =
static_cast<device::mojom::blink::XRHandJoint>(i);
joints_[i] = MakeGarbageCollected<XRJointSpace>(
this, input_source->session(), nullptr, joint, 0.0f,
input_source->xr_handedness());
}
updateFromHandTrackingData(state, input_source);
}
XRJointSpace* XRHand::get(const String& key) {
device::mojom::blink::XRHandJoint joint = StringToMojomHandJoint(key);
unsigned index = static_cast<unsigned>(joint);
return joints_[index];
}
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<TransformationMatrix> mojo_from_joint = nullptr;
if (hand_joint->mojo_from_joint) {
new_poses = true;
mojo_from_joint =
std::make_unique<TransformationMatrix>(*hand_joint->mojo_from_joint);
} else {
new_missing_poses = true;
}
joints_[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_ =
!base::ranges::all_of(joints_, &XRJointSpace::MojoFromNative);
}
}
XRHand::IterationSource* XRHand::StartIteration(
ScriptState* script_state,
ExceptionState& exception_state) {
return MakeGarbageCollected<XRHandIterationSource>(joints_);
}
void XRHand::Trace(Visitor* visitor) const {
visitor->Trace(joints_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink