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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Panning to rotate 360Video - Can't set Camera's local rotation #103

Closed
vjtc0n opened this issue Dec 5, 2017 · 14 comments
Closed

Comments

@vjtc0n
Copy link

vjtc0n commented Dec 5, 2017

Hello Viro Team,

I haven't found out any ways to use (a) finger(s) to change the view in Viro360Video (just mono mode, not cardboard).
I also tried to use PanResponder but still not working.
For example, when we want to change the view, we must turn around our bodies, therefore changing the view.
Now I want to use fingers to turn around the view, just like facebook VRVideo, any chances to do this right now?
Thank you!

@vjtc0n
Copy link
Author

vjtc0n commented Dec 6, 2017 via email

@dthian
Copy link
Member

dthian commented Dec 7, 2017

Hi @vjtc0n, I've attempted to get a working code example as shown in the screen shot below:

ezgif-5-546825fb6d

The sample code for containing the panResponder and moving the view point is as shown:

// Sample pan responder that you can create in component will mount.
this._panResponder = PanResponder.create({
        onMoveShouldSetResponderCapture: () => true,
        onMoveShouldSetPanResponderCapture: () => true,
        onPanResponderGrant: (e, gestureState) => {},

        onPanResponderMove: (evt, gestureState) => {
          that._updatePanAngleOffset(gestureState, true);
        },
        onPanResponderRelease: (e, gestureState) => {
          that._updatePanAngleOffset(gestureState, false);
        }
      });
    }

// All rotation offset calculations are done here.
_updatePanAngleOffset(gestureState, isPanning){
            var movementSensitivityX = 100;

            // Create our horizontal offsets, normalize, and then add it as the offset angle for rotating.
            // Note that 730 is the width of the entire screen for demo purposes.
            var distanceMovedX = gestureState.x0 - gestureState.moveX;
            var normalizedDistanceMovedX = distanceMovedX/730;
            var newAngleX = normalizedDistanceMovedX * movementSensitivityX;

            if (isPanning){
                // This component can be either your 360 background, or camera.
                this._component.setNativeProps({
                  rotation: [0, this._savedEndAngleX + newAngleX, 0]
                });
            } else {
              this._savedEndAngleX = this._savedEndAngleX + newAngleX;
            }
}

If you do want to enable vertical rotation as well, so that the user can then pan up and down at the same time, you would hit a Viro Bug - There is an issue where setting the camera rotation does not consider the device’s current ‘head/tilt rotation’, resulting in a bug where the camera does not rotate along the forward vector of where it is currently facing in. For example, the user can turn his device left, pan up and down, and this would result in the world “titlting to the right”.

As a mitigation, I would suggest locking the camera to only rotate horizontally, as shown in the example code above. This should still give the user the freedom to "move / rotate" in these scene, where the user can pan, then look around, and then pan again.

With regards to adding vertical rotation support, I'll rename this bug to properly and more accurately reflect the ask that is required to achieve this. I will also be filing a bug on our back log so we can take a look at this. As soon as this is patched in a future release, we'll update this issue.

@dthian dthian changed the title Need support for changing view's position in Viro360Video by hand's gestures Support for Panning to rotate 360Video - Can't set Camera's local rotation Dec 7, 2017
@vjtc0n
Copy link
Author

vjtc0n commented Dec 7, 2017

Thank you, Viro Team.
So nice to hear that. I'll lock the Vertical Pan as long as waiting for the new release.

@vjtc0n
Copy link
Author

vjtc0n commented Dec 7, 2017

resetToZeroPostition() {
    if (this.videoRef) {
      const movementSensitivityX = 200;
      const delta = this._savedEndAngleX / (this.currentDeviceWidth * 200) * movementSensitivityX;
      let savedEndAngleXLeft = this._savedEndAngleX;
      console.log('begin save', savedEndAngleXLeft);
      console.log('delta', delta);
      while (savedEndAngleXLeft > delta) {
        savedEndAngleXLeft -= delta;
        console.log(savedEndAngleXLeft);
        this.videoRef.setNativeProps({
          rotation: [0, savedEndAngleXLeft, 0]
        });
      }
      this.videoRef.setNativeProps({
        rotation: [0, 0, 0]
      });
      this._savedEndAngleX = 0;
    }
  }

Hello @dthian , thank you for your support.
Sometimes we want to reset the postition to the beginning.
The above code is my sample code, but it is not working properly.
Instead of changing the view smoothly, it immediately goes to [0,0,0], losing the animation which is made of my "while" loop.
Any suggestion for this?
Thanks.

@dthian
Copy link
Member

dthian commented Dec 7, 2017

Hi @vjtc0n, unfortunately you will not be able to achieve any animation with the code sample above - this is because the while loop will most likely be executed (looped to it's satisfying condition) in a very quick succession within the duration of a frame.

To achieve an animation look, you would need to:

  1. Register a rotation animation with the the AnimationManager in Viro - For example, properties:{rotateY:0}
  2. Set the animation property on your component you want to rotate back and run it - For example,
    this._component.setNativeProps({
    animation={{name:'resetBackToBeginning', run:true}}
    });

Note for step 2 above, you might need to call it twice with run:false then run:true because of how react handles states.

You can view more of the animation guides here

Let us know if you experience any problems trying to achieve this.

@vjtc0n
Copy link
Author

vjtc0n commented Dec 7, 2017

@connect(state => ({ vrPlayer: getVRPlayer(state) }), {
  ...commonActions,
  ...vrActions,
  ...soundActions
})
export default class VrVideo extends React.Component {
   resetToZeroPostition() {
    if (this.videoRef) {
      this.videoRef.setNativeProps({
        animation: {
          name: 'resetBackToBeginning',
          run: true,
          onFinish: this.finishResetToZeroPostition
        }
      });
      this._savedEndAngleX = 0;
    }
  }

  finishResetToZeroPostition() {
    if (this.videoRef) {
      this.videoRef.setNativeProps({
        animation: {
          name: 'resetBackToBeginning',
          run: false,
          onFinish: this.finishResetToZeroPostition
        }
      });
      this._savedEndAngleX = 0;
    }
  }
  render() {
    return (
    ...
    <ViroSceneNavigator
          debug={false}
          vrModeEnabled={vrModeEnabled}
          apiKey={configs.vrKey}
          initialScene={{
            scene: () => (
              <ViroScene>
                <Viro360Video
                  ref={ref => (this.videoRef = ref)}
                  onBufferStart={this.onBufferStart.bind(this)}
                  onUpdateTime={this.onUpdateTime}
                  onError={() => this.setState({ error: true })}
                  onFinish={() => {}}
                  paused={this.state.paused}
                  loop
                  source={source}
                  animation={{
                    name: 'resetBackToBeginning',
                    run: true,
                    onFinish: this.finishResetToZeroPostition
                  }}
                />
              </ViroScene>
            )
          }}
          onExitViro={this.onDone.bind(this)}
        />
    ...
    )
}
}

ViroAnimations.registerAnimations({
  resetBackToBeginning: {
    properties: { rotateY: 0 },
    easing: 'EaseInEaseOut',
    duration: 1000
  }
});

Here is my sample code, it does nothing.
Does animation support VR360Video ?
// resetToZeroPostition() will be triggered by a Button.

@dthian
Copy link
Member

dthian commented Dec 7, 2017

Hmm, VR360Video may not support animations at this time. However, I would strongly recommend to animate a ViroCamera in the scene, rather than the scene around the camera - could you try that instead and see if it works? Adding a camera should be as simple as

// Don't forget to import
<ViroCamera
     active={true}
     ref={ref => (this.cameraRef = ref)} />

Let us know if it doesn't work and we'll take a look at it first thing tomorrow

@vjtc0n
Copy link
Author

vjtc0n commented Dec 7, 2017

resetToZeroPostition() {
    if (this.cameraRef) {
      this.cameraRef.setNativeProps({
        animation: {
          name: 'resetBackToBeginning',
          run: true,
          onFinish: this.finishResetToZeroPostition
        }
      });
      this._savedEndAngleX = 0;
    }
  }

  finishResetToZeroPostition() {
    if (this.cameraRef) {
      this.cameraRef.setNativeProps({
        animation: {
          name: 'resetBackToBeginning',
          run: false,
          onFinish: this.finishResetToZeroPostition
        }
      });
      this._savedEndAngleX = 0;
    }
  }

render() {
    return (
    ...
    <ViroSceneNavigator
          debug={false}
          vrModeEnabled={vrModeEnabled}
          apiKey={configs.vrKey}
          initialScene={{
            scene: () => (
              <ViroScene>
                <ViroCamera
                  active
                  ref={ref => (this.cameraRef = ref)}
                  animation={{
                    name: 'resetBackToBeginning',
                    run: true,
                    onFinish: this.finishResetToZeroPostition
                  }}
                />
                <Viro360Video
                  ref={ref => (this.videoRef = ref)}
                  onBufferStart={this.onBufferStart.bind(this)}
                  onUpdateTime={this.onUpdateTime}
                  onError={() => this.setState({ error: true })}
                  onFinish={() => {}}
                  paused={this.state.paused}
                  loop
                  source={source}
                />
              </ViroScene>
            )
          }}
          onExitViro={this.onDone.bind(this)}
        />
    ...
    )
}

ViroAnimations.registerAnimations({
  resetBackToBeginning: {
    properties: { rotateY: 0 },
    easing: 'EaseInEaseOut',
    duration: 1000
  }
});

Now the animation works like a charm, but I faced another problem.
When you rotate left/right < 90 degrees, it turns back to the beginning position, but when rotating left/right > 90 degrees, it will turn to the opposite side (180 degrees).
I mean that properties: { rotateY: 0 } is different from this._savedEndAngleX = 0;

How could I dynamically fix this?
Thank you.

@dthian
Copy link
Member

dthian commented Dec 8, 2017

Hey @vjtc0n, could you also try setting rotateX and rotateZ to 0 as well?
I'm wondering if what you are seeing is an artifact of the Renderer successfully rotating Y to 0, but at the manipulation of the other angles. Thanks!

@dam00n
Copy link
Collaborator

dam00n commented Jan 6, 2018

Closing this issue due to inactivity. Please reopen if the solution above did not work for you.

@intimateo
Copy link

intimateo commented May 2, 2018

Hey @dthian but where that I have to put the {...this._panResponder.panHandlers}
because my structure is this

<View style={styles.container} {...this._panResponder.panHandlers}>
      <ViroVRSceneNavigator {...this.state.sharedProps}
        initialScene={{scene: () => (
        <ViroScene onClick={() => this.tapedscene()}>
            <Viro360Video ref={ref => (this.videoRef = ref)} 
              source={{source}}
              volume={1.0}
              loop={false}
              muted={false}
              paused={this.state.videoPaused}
              onBufferEnd={this.onBufferEnd.bind(this)}
              onBufferStart={this.onBufferStart.bind(this)}
              onUpdateTime={this.onUpdateTime.bind(this)}
              onFinish={() => this.onFinish()}
              rotation={[0,90,0]}/>
              <ViroSpinner 
                type='Light'
                position={[0, 0, -7]}
                transformBehaviors={["billboard"]}
                visible={this.state.Activityshow}
              />
        </ViroScene>
        
        )}} onExitViro={this._exitViro} vrModeEnabled={this.props.VRtype}/>
   <View>
   #some react native components
   </View>
</View>

I don't get anything when I'm panning but If I remove block and his content I get events of PanResponder, so I don't know what I have to do to get PanResponder data

@dthian
Copy link
Member

dthian commented May 2, 2018

Hi @intimateo, thanks for reaching out unfortunately the above mitigation only works for Android platforms (the pan handlers would be applied to a parent React view that encapsulates ViroVRSceneNav). This is because on iOS, Google's own GVR controls creates a window on top of React's views, effectively "Eating up" all events. Thus, when you remove ViroVRSceneNav (and therefore GVR), pan handlers work properly as intended.

Apologies for the roundabout approach / explanation. To get around this, we plan to build native pan handling support - You can track the progress of this here. Please chime in there as well that you need this support so that we can have better numbers on priority.

@apurvasaxena
Copy link

How to support this in android with java code as there is no panResponder in android?

@Ashkan-Oliaie
Copy link

still no support for vertical rotation of the camera ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants
@dam00n @dthian @intimateo @apurvasaxena @vjtc0n @Ashkan-Oliaie and others