react-native-ar / react-native-arkit

React Native binding for iOS ARKit
MIT License
1.73k stars 139 forks source link

Examples for hittest? #164

Open elderbas opened 6 years ago

elderbas commented 6 years ago

The example in documentation with the

import { ARKit } from 'react-native-arkit'

//...
const result = await ARKit.hitTestSceneObjects(point);

Isn't very clear to me how I'm supposed to use hit test.

Could we add that in the example somewhere? Perhaps detecting when a given position is detected on the screen.

macrozone commented 6 years ago

true, I would like to have a guide/examples section.

const result = await ARKit.hitTestSceneObjects(point);

returns all objects that have bin hit by the "ray" coming out of the camera at screenpoint point (x,y).

typical usecase it to tap/click on objects on the screen, where you give the click position to ARKit.hitTestSceneObjects(clickPoint)

elderbas commented 6 years ago

@macrozone

I'm familiar with mostly the react-native or react style of event flow, like onTouch, onPress, then handle logic from within those callbacks.

It's still not clear to me where I would put const result = await ARKit.hitTestSceneObjects(point);

Inside of a callback of a ARKit component prop somewhere? Inside componentDidMount or something?

The most common cases I could think of know that I would want to know how to handle...

and then being able to use that captured location to then change the location of an asset, or to place a new one, or remove/change the one pressed on

code-matt commented 6 years ago

@elderbas New to this lib myself but I went about it this way to hook up simple tap to place objects example

export default class App extends Component {
  constructor (props) {
    super(props)

    this.touchTimeout = false
    this.state = {
      tapPosition: {x: 0, y: 0, z: 0}
    }
  }

  componentDidMount () {
    this.touchTimeout = false
  }

  resetTouchTimeout = () => {
    this.touchTimeout = false
  }

  handleResponderMove (e) {
    if (!this.touchTimeout) {
      this.touchTimeout = true
      setTimeout(this.resetTouchTimeout, 1000)
      this.hitTestPlanes({ x: e.nativeEvent.pageX, y: e.nativeEvent.pageY })
    }
  }

  hitTestPlanes = async (location) => {
    const hits = await ARKit.hitTestPlanes(location, 1)
    if (hits.results.length) {
      this.setState({
        tapPosition: hits.results[0].position
      })
    }
  }

  render() {
    return (
      <View
        style={styles.container}
        onResponderMove={this.handleResponderMove.bind(this)}
        onStartShouldSetResponder={() => true}
        onMoveShouldSetResponder={() => true}
      >
        <ARKit
            ...

the demo cube's position being this.state.tapPosition

code-matt commented 6 years ago

Just kidding, that is good if you want to drag things around but

export default class App extends Component {
  state = {
    tapPosition: {x: 0, y: 0, z: 0}
  }

  handleResponderMove (e) {
    this.hitTestPlanes({ x: e.nativeEvent.pageX, y: e.nativeEvent.pageY })
  }

  hitTestPlanes = async (location) => {
    const hits = await ARKit.hitTestPlanes(location, 1)
    if (hits.results.length) {
      this.setState({
        tapPosition: hits.results[0].position
      })
    }
  }

  render() {
    return (
      <View
        style={styles.container}
        onResponderMove={this.handleResponderMove.bind(this)}
        onStartShouldSetResponder={() => true}
        onMoveShouldSetResponder={() => false}
      >
        <ARKit
            ...

will do for just a hit test

joseocasioserra commented 5 years ago

That is nice, but what if I have 10 objects and I want to know which one I clicked is? I am trying to use hitTestSceneObjects, but the id coming back on the 'results' response is a random ID that changes every time.

code-matt commented 5 years ago

@joseocasioserra You can give the <ARKit.Plane /> or whatever an id prop

<ARKit.Plane
  id={`sometype_${234234}`}
/>

Then, after you do your hit test and have a result, get the type so you can have different kinds of entities and also id

      const type = hits.results.length && hits.results[0].id.split('_')[0]
      const id = hits.results.length && hits.results[0].id.split('_')[1]