nvanbenschoten / motion

An Android library allowing images to exhibit a parallax effect that reacts to the device's tilt
Apache License 2.0
776 stars 89 forks source link

Parallax effect does not work when device is vertical or near vertical. #4

Closed jasonpolites closed 9 years ago

jasonpolites commented 10 years ago

The "roll" (rotation on y axis) doesn't work when the "pitch" (rotation on the x axis) is close to PI/2 (90 degrees). At this point "yaw" (rotation on the z axis) actually effects the left/right parallax.

I've seen this happen before when working with the sensors. As pitch increases, the distinction between roll and yaw is unclear (makes sense, of you "roll" the device when it's vertical you are actually changing the "yaw" with respect to world coordinates)

I haven't found a good solution to this anywhere, and unfortunately although the library performs well when the device is flat, devices are rarely flat and most often will have a pitch of somewhere between 0 and PI/2. Typically somewhere around PI/4 which "half works" with the method you've used.

nvanbenschoten commented 10 years ago

You're absolutely right about this issue. I've been trying to fix it for quite some time but have yet to find an optimal solution so have made a design decision to stick with the approach that results in no glaring jumps or jerky behavior.

One attempted solution I tried was to scale the roll by the cosine of the pitch, essentially artificially multiplying the lowered sensitivity at close to vertical angles. This solution worked nearly perfect at combating the issue until the phone was brought to an exact vertical, where it fell apart. The problem was that the math behind the sensor interpretation resulted in 0 being multiplied by infinity, making the image unstable, indeterminate, and very jumpy.

The other solution was to mesh the roll and the yaw together and scale them respectively based on the pitch. This solution still seems feasible to me, but I was unable to make it smooth enough to be acceptable. I also found that by relying on the yaw (which is basically a compass at the vertical), I fell into the issue of not knowing where the user thought "forward" was, and thus, where to zero my calculations from. I attempted some exponential averaging to try to combat this, but I found this solution to suboptimal as well.

I am very open to suggestions as this issue has bugged me for quite sometime, but for now, I still believe the best solution is the one that results in no jumping of the image or any other unexpected behavior, even if it means lowered sensitivity at higher angles.

jasonpolites commented 10 years ago

I agree, and have faced similar issues. The thing that annoys me the most is yaw rotation affecting roll. When flat this doesn't happen, but as pitch increases you'll see roll values change with yaw rotation. This is really counter-intuitive for the user and destroys the illusion of the effect.

I'll keep tinkering also and if I reach a viable solution I'll let you know.

Cheers,

Jason. On Jun 2, 2014 9:06 PM, "Nathan VanBenschoten" notifications@github.com wrote:

You're absolutely right about this issue. I've been trying to fix it for quite some time but have yet to find an optimal solution so have made a design decision to stick with the approach that results in no glaring jumps or jerky behavior.

One attempted solution I tried was to scale the roll by the cosine of the pitch, essentially artificially multiplying the lowered sensitivity at close to vertical angles. This solution worked nearly perfect at combating the issue until the phone was brought to an exact vertical, where it fell apart. The problem was that the math behind the sensor interpretation resulted in 0 being multiplied by infinity, making the image unstable, indeterminate, and very jumpy.

The other solution was to mesh the roll and the yaw together and scale them respectively based on the pitch. This solution still seems feasible to me, but I was unable to make it smooth enough to be acceptable. I also found that by relying on the yaw (which is basically a compass at the vertical), I fell into the issue of not knowing where the user thought "forward" was, and thus, where to zero my calculations from. I attempted some exponential averaging to try to combat this, but I found this solution to suboptimal as well.

I am very open to suggestions as this issue has bugged me for quite sometime, but for now, I still believe the best solution is the one that results in no jumping of the image or any other unexpected behavior, even if it means lowered sensitivity at higher angles.

— Reply to this email directly or view it on GitHub https://github.com/nvanbenschoten/motion/issues/4#issuecomment-44917960.

gbrbks commented 10 years ago

Hello guys!

I guess this is the so called Gimbal lock problem, and the solution is the Quaternion based calculations http://en.wikipedia.org/wiki/Gimbal_lock http://en.wikipedia.org/wiki/Quaternion

Cheers, Gabor