viromedia / viro

ViroReact: AR and VR using React Native
MIT License
2.3k stars 482 forks source link

Building Recognition using AR Viromedia #605

Open JoSuarezC opened 5 years ago

JoSuarezC commented 5 years ago

Hello Viro Admins.

I'm developping an app using Viromedia. In this app I want to recognize a specific house or building and activate an animation above it. I got a guide by this issue: https://github.com/viromedia/viro/issues/131 setting the specific 2D Coordinate where I want to place the animation. However, it does not work, the coordinates where the animation it placed is not always exactly. May you help me if there is any mistake on my attached code?

Also I tried using Image Tracking, setting a photo of the house that I want to track but it was not recognized when I was in front of it.

Is there any other option that I can use to build my app using Viromedia?

Thank you so much for your help.

export default class HelloWorldSceneAR extends Component {

  constructor() {
    super();

    this.state = {
      text : "Initializing AR...",
      latitude: 0,
      longitude: 0,
      objectXPos: 0,
      objectZPos: 0,
      heading: 0,
      coordinateString: "Sin datos",
      coordinateLatLongString: "Sin datos",
      error: null

    };
    this._onInitialized = this._onInitialized.bind(this);
    this._latLongToMerc = this._latLongToMerc.bind(this);
    this._transformPointToAR = this._transformPointToAR.bind(this);
  }

  componentDidMount(){
    let myself = this;
    const degree_update_rate = 3; // Number of degrees changed before the callback is triggered
      RNSimpleCompass.start(degree_update_rate, (degree) => {
        console.log('You are facing', degree);
        myself.setState({
          heading: degree
        });
        RNSimpleCompass.stop();
      });
  }

  render() { 
    return (
      <ViroARScene onTrackingUpdated={this._onInitialized}>
        <ViroText text={this.state.heading+"||"+this.state.coordinateLatLongString + " || " +this.state.coordinateXYZString}
            scale={[.1, .1, .1]} height={5} width={4} position={[0, 0, -.1]} style={styles.helloWorldTextStyle} />
        <ViroText text={"PUNTO"}
            scale={[1, 1, 1]} height={5} width={4} position={[this.state.objectXPos, 0, this.state.objectZPos]} style={styles.helloWorldTextStyle} />
      </ViroARScene>

    );

  }

  _transformPointToAR(lat, long) {

    var objPoint = this._latLongToMerc(9.850811, -83.923636); 
    var devicePoint = this._latLongToMerc(lat, long); 

    // latitude(north,south) maps to the z axis in AR
    // longitude(east, west) maps to the x axis in AR

    var objFinalPosZ = objPoint.y - devicePoint.y;
    var objFinalPosX = objPoint.x - devicePoint.x;

    //var objFinalPosZ = 2;
    //var objFinalPosX = 0;

    let angle = this.state.heading * Math.PI/180;
    console.log("heading:" + this.state.heading);
    console.log("Cos: "+ Math.cos(angle));
    console.log("Sen: "+ Math.sin(angle));
    let newRotatedX = objFinalPosX * Math.cos(angle) - objFinalPosZ * Math.sin(angle);
    let newRotatedZ = objFinalPosZ * Math.cos(angle) + objFinalPosX * Math.sin(angle);  

    //flip the z, as negative z(is in front of us which is north, pos z is behind(south).

    return ({x:newRotatedX, z:-newRotatedZ});
  }

  // Converts Lat and Long to Mercator projection
  _latLongToMerc(lat_deg, lon_deg) { 
    let lon_rad = (lon_deg / 180.0 * Math.PI)
    var lat_rad = (lat_deg / 180.0 * Math.PI)
    var sm_a = 6378137.0
    var xmeters  = sm_a * lon_rad
    var ymeters = sm_a * Math.log((Math.sin(lat_rad) + 1) / Math.cos(lat_rad))
    return ({x:xmeters, y:ymeters});
 }

  _onInitialized(state, reason) {
    if (state == ViroConstants.TRACKING_NORMAL){
      if (checkLocalizationPermission()) {
        Geolocation.watchPosition(
          (position) => {

            var objetPositionAR = this._transformPointToAR(position.coords.latitude, position.coords.longitude);

            this.setState({
              latitude: position.coords.latitude,
              longitude: position.coords.longitude,
              objectXPos: objetPositionAR.x,
              objectZPos: objetPositionAR.z,
              coordinateXYZString: "[" + String(objetPositionAR.x) + ", 0, " + String(objetPositionAR.z) + "]",
              coordinateLatLongString: "Lat: " + String(position.coords.latitude) + " ** Lng: " + String(position.coords.longitude),
              error: null   
            });
          },
          (error) => {
              this.setState({
                error: error.message
              });
          },
          { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
        );
      } 
      else {
        this.setState({
          error : "Permission Denied"
        });
      }
    } else if (state == ViroConstants.TRACKING_NONE){
      this.setState({
        coordinateXYZString: "Error",
        coordinateLatLongString: "Error",
        error: null   
      });
    }
  }
}

async function checkLocalizationPermission(){
  try {
    const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION);
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      return true;
    }
  } catch (err) {
    console.warn(err);
  }
  return false;
}
JoaquinBuxo commented 5 years ago

Hi @JoSuarezC!! I'm trying to do something similar but it doesn't work either... Have you achieved any progress? Are you developing with iOS? Maybe with ViroARObjectMarker using a 3D Model of the building could work (I don't have iPhone to tested)

JoSuarezC commented 5 years ago

Hello. I haven't tried iOS yet. I changed the scale of the 3D Object and it seems to work in a better way. The geolocalization is not perfect, sometimes there is a little difference of some meters but I will work on this way.

        <ViroNode position={[this.state.objectXPosPretil, 0, this.state.objectZPosPretil]} dragType="FixedToWorld" onDrag={()=>{}} >
          <Viro3DObject
            onClick={this._objectOnClick}
            source={require('./res/emoji_smile/emoji_smile.vrx')}
            resources={[require('./res/emoji_smile/emoji_smile_diffuse.png'),
                require('./res/emoji_smile/emoji_smile_normal.png'),
                require('./res/emoji_smile/emoji_smile_specular.png')]}
            position={[this.state.objectXPosPretil, 2, this.state.objectZPosPretil]}
            scale={[20,20,20]}
            type="VRX" />
        </ViroNode>
      </ViroARScene>