xrift-grab
v0.1.0
Published
Hand-grip VR grab mechanic for react-three-fiber / WebXR worlds — VRグリップ掴み機構
Maintainers
Readme
xrift-grab
react-three-fiber / WebXRアプリ向けの、VRコントローラのグリップで握って持ち歩く掴み機構。
@xrift/world-components(XRift SDK)は、レイキャストで狙って浮かせて置き直す配置ツール系の<Grabbable>は提供しているが、「コントローラのグリップボタンで物理的に握る→握った瞬間の向きのまま手にくっつく→両手で別々の物を同時に持てる→離すとその場に浮いて留まる」という、道具を持ち歩くタイプの掴み方は提供していない。本パッケージはそれを埋める。
XRiftに限らず、react・three・@react-three/fiberだけに依存する汎用WebXRライブラリ。
Install
npm install xrift-grabpeerDependencies: react >=19, three >=0.176.0, @react-three/fiber >=9
Usage
import { XRGrabProvider, useGrabbable } from 'xrift-grab'
import { Vector3, Quaternion } from 'three'
import { useFrame } from '@react-three/fiber'
import { useRef } from 'react'
function Pencil() {
const meshRef = useRef<Group>(null)
const grab = useGrabbable({
id: 'pencil-1',
worldPose: (outPos, outQuat) => {
// 今の置き位置・向き(ラック上など)
outPos.set(0, 1, 0)
outQuat.identity()
},
onGrabStart: (hand, viaGrip) => console.log(`${hand}が掴んだ (grip: ${viaGrip})`),
onDrop: (pose) => console.log('離した', pose),
})
useFrame(() => {
const p = new Vector3()
const q = new Quaternion()
if (grab.getAttachedPose(p, q)) {
meshRef.current?.position.copy(p)
meshRef.current?.quaternion.copy(q)
}
})
return <mesh ref={meshRef}>...</mesh>
}
function World() {
return (
<XRGrabProvider grabRadius={0.45}>
<Pencil />
</XRGrabProvider>
)
}クリック/レイキャストなど、グリップ以外の手段で取らせたい場合は grab.grabViaClick() を呼ぶ(defaultOffset を指定していれば、握った瞬間の相対姿勢の代わりにその既定オフセットが使われる)。
既知の制約
- グリップ操作(
squeezestart/squeezeend)はハンドトラッキングのみのセッションでは発火しないことが多い。ハンドトラッキング環境で掴ませたい場合は、selectstart(ピンチ)を検出してgrabViaClick()を呼ぶ形で回避する - マルチプレイの「誰が持っているか」の同期・所有権はスコープ外。
isFreeオプションとonGrabStart/onDropコールバックを使い、アプリ側の同期機構(例: XRiftのuseInstanceState)と組み合わせること
License
MIT
