Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Great Library ! How to intercept Motion data #247

Open
supertick opened this issue Mar 1, 2023 · 3 comments
Open

[Question] Great Library ! How to intercept Motion data #247

supertick opened this issue Mar 1, 2023 · 3 comments
Labels
question A general question or query about WebXR or react-xr

Comments

@supertick
Copy link

supertick commented Mar 1, 2023

I tried a few examples and they seemed to work very well.
This one I'm a bit stumped 馃
It seems very simple - I'm just trying to intercept the position and orientation of a Quest 2 headset and left/right controllers.

import React, { useEffect } from 'react';
import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { useController } from '@react-three/xr';

const WebXr = () => {
  const { gl } = useThree();
  const leftController = useController('left');
  const rightController = useController('right');
  const gazeController = useController('gaze');

  useEffect(() => {
    const handleControllerInput = (event) => {
      console.log(event.target.name, event.target.position.toArray(), event.target.rotation.toArray());
    };

    leftController.addEventListener('selectstart', handleControllerInput);
    rightController.addEventListener('selectstart', handleControllerInput);
    gazeController.addEventListener('selectstart', handleControllerInput);

    return () => {
      leftController.removeEventListener('selectstart', handleControllerInput);
      rightController.removeEventListener('selectstart', handleControllerInput);
      gazeController.removeEventListener('selectstart', handleControllerInput);
    };
  }, [leftController, rightController, gazeController]);

  useFrame(() => {
    gl.xr.isPresenting && console.log(leftController.position.toArray(), rightController.position.toArray(), gazeController.position.toArray());
  });

  return (
    <Canvas>
      <mesh position={[0, 0, -3]}>
        <boxBufferGeometry args={[2, 2, 2]} />
        <meshBasicMaterial color="white" />
      </mesh>
    </Canvas>
  );
};

export default WebXr;

It seems to transpile fine, but in the console I'm getting ...
image
It's all being used in Canvas no?
Or, am I thinking about this wrong - do I need references in other sub components?
Is there a simple example which prints the data I'm looking for to console, it seems to have eluded me...
Any help is most appreciated :)

@CodyJasonBennett
Copy link
Member

Your WebXR component itself relies on R3F hooks which can only be called within a component wrapped in <Canvas /> since it relies on context for hooks.

import React, { useEffect } from 'react';
import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { useController } from '@react-three/xr';

const WebXr = () => {
  const { gl } = useThree();
  const leftController = useController('left');
  const rightController = useController('right');
  const gazeController = useController('gaze');

  useEffect(() => {
    const handleControllerInput = (event) => {
      console.log(event.target.name, event.target.position.toArray(), event.target.rotation.toArray());
    };

    leftController.addEventListener('selectstart', handleControllerInput);
    rightController.addEventListener('selectstart', handleControllerInput);
    gazeController.addEventListener('selectstart', handleControllerInput);

    return () => {
      leftController.removeEventListener('selectstart', handleControllerInput);
      rightController.removeEventListener('selectstart', handleControllerInput);
      gazeController.removeEventListener('selectstart', handleControllerInput);
    };
  }, [leftController, rightController, gazeController]);

  useFrame(() => {
    gl.xr.isPresenting && console.log(leftController.position.toArray(), rightController.position.toArray(), gazeController.position.toArray());
  });

  return (
    <mesh position={[0, 0, -3]}>
      <boxBufferGeometry args={[2, 2, 2]} />
      <meshBasicMaterial color="white" />
    </mesh>
  );
};

export default () => (
  <Canvas>
    <WebXr/>
  </Canvas>
);

@CodyJasonBennett CodyJasonBennett added the question A general question or query about WebXR or react-xr label Mar 1, 2023
@supertick supertick changed the title Great Library ! [Question] Great Library ! How to intercept Motion data Mar 1, 2023
@supertick
Copy link
Author

I think I understand and appreciate what you tried to do with the default export ...
but it gives the same error ...

Might there be a working example which does the same thing ? Maybe just for the headset ?

@CodyJasonBennett
Copy link
Member

I'd see our examples:

import * as React from 'react'
import * as THREE from 'three'
import { VRButton, XR, Hands, useXR, Interactive, useHitTest, Controllers } from '@react-three/xr'
import { Box, Text } from '@react-three/drei'
import { useFrame, Canvas } from '@react-three/fiber'
function Button(props: JSX.IntrinsicElements['mesh']) {
const [hover, setHover] = React.useState(false)
const [color, setColor] = React.useState(0x123456)
return (
<Interactive onSelect={() => setColor((Math.random() * 0xffffff) | 0)} onHover={() => setHover(true)} onBlur={() => setHover(false)}>
<Box {...props} args={[0.4, 0.1, 0.1]} scale={hover ? 1.5 : 1}>
<meshStandardMaterial color={color} />
{false && (
<Text position={[0, 0, 0.06]} fontSize={0.05} color="#000" anchorX="center" anchorY="middle">
Hello react-xr!
</Text>
)}
</Box>
</Interactive>
)
}
function PlayerExample() {
const player = useXR((state) => state.player)
useFrame(() => void (player.rotation.x = player.rotation.y += 0.01))
return null
}
function HitTestExample() {
const boxRef = React.useRef<THREE.Mesh>(null!)
useHitTest((hitMatrix) => {
hitMatrix.decompose(boxRef.current.position, boxRef.current.quaternion, boxRef.current.scale)
})
return <Box ref={boxRef} args={[0.1, 0.1, 0.1]} />
}
export function App() {
return (
<>
<VRButton onError={(e) => console.error(e)} />
<Canvas>
<XR>
<ambientLight intensity={0.5} />
<pointLight position={[5, 5, 5]} />
<Hands
// modelLeft="/hand-left.gltf"
// modelRight="/hand-right.gltf"
/>
<Button position={[0, 0.8, -1]} />
<Controllers />
{false && <PlayerExample />}
{false && <HitTestExample />}
</XR>
</Canvas>
</>
)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question A general question or query about WebXR or react-xr
Projects
None yet
Development

No branches or pull requests

2 participants