2014-02-12 50 views
0

我想添加數學來控制與陀螺儀的全景和掙扎。這是一個內置於AS3的移動應用程序。從AS3陀螺儀計算全景角的數學

我已經從陀螺儀(x和y)獲得了數據,並且獲得了當前角度(平移和傾斜)。我想要做的就是根據陀螺儀的數據以新角度更新cameraController。

我一直在試圖將我在https://github.com/fieldOfView/krpano_fovplugins/blob/master/gyro/source/gyro.source.js上找到的Javascript轉換成ActionScript3,它有點作品 - 但並不是真的。

編輯

謝謝,我想這些變化和我說相機膠捲回來,因爲歐拉的數學需要它,它運行,但也有一些是錯誤的數學。

全景似乎只是漂移和離開,過了一段時間移動電話,另一種方式它漂移,然後向右移動。

你能看到我從Javascript中丟失的重要東西嗎?

import com.adobe.nativeExtensions.GyroscopeEvent; 

import flash.events.Event; 
import flash.geom.Orientation3D; 

public class GyroscopeMaths 
{ 
    public function GyroscopeMaths() 
    { 
     super(); 
    } 

    private var isTopAccessible:Boolean = false; 
    private var isDeviceAvailable:Boolean; 
    private var isEnabled:Boolean = false; 
    private var vElasticity:Number = 0; 
    private var isVRelative:Boolean = false; 
    private var isCamRoll:Boolean = false; 
    private var friction:Number = 0.5; 
    private var isTouching:Boolean = false; 
    private var validSample:Boolean = false; 
    private var firstSample:* = null; 
    private var hOffset:Number = 0; 
    private var vOffset:Number = 0; 
    private var hLookAt:Number = 0; 
    private var vLookAt:Number = 0; 
    private var camRoll:Number = 0; 
    private var vLookAtNow:Number = 0; 
    private var hLookAtNow:Number = 0; 
    private var hSpeed:Number = 0; 
    private var vSpeed:Number = 0; 
    private var vElasticSpeed:Number = 0; 
    private var camRollNow:Number; 
    private var pitch:Number; 
    private var yaw:Number; 
    private var altYaw:Number; 
    private var factor:Number; 
    private var degRad:Number = Math.PI/180; 

    public function handleDeviceOrientation(x:Number, y:Number, z:Number):void { 
     // Process event.alpha, event.beta and event.gamma 
     var orientation:* = rotateEuler({ 
      "yaw":y * degRad, 
      "pitch":x * degRad, 
      "roll": z * degRad 
     }); 
     yaw = wrapAngle(orientation.yaw/degRad); 
     pitch = orientation.pitch/degRad; 
     altYaw = yaw, factor; 
     hLookAtNow = Pano.instance.pan; 
     vLookAtNow = Pano.instance.tilt; 
     hSpeed = hLookAtNow - hLookAt, 
      vSpeed = vLookAtNow - vLookAt; 

     // Ignore all sample until we get a sample that is different from the first sample 
     if (!validSample) { 
      if (firstSample == null) { 
       firstSample = orientation; 
      } else { 
       if (orientation.yaw != firstSample.yaw || orientation.pitch != firstSample.pitch || orientation.roll != firstSample.roll) { 
        firstSample = null; 
        validSample = true; 
        if (isVRelative) { 
         vOffset = -pitch; 
        } 
       } 
      } 
      return; 
     } 

     // Fix gimbal lock 
     if (Math.abs(pitch) > 70) { 
      altYaw = y; 


      var altYaw:Number = wrapAngle(altYaw); 
      if (Math.abs(altYaw - yaw) > 180) { 
       altYaw += (altYaw < yaw) ? 360 :-360; 
      } 

      var factor:Number = Math.min(1, (Math.abs(pitch) - 70)/10); 
      yaw = yaw * (1 - factor) + altYaw * factor; 

      //camRoll *= (1 - factor); 
     } 

     // Track view change since last orientation event 
     // ie:user has manually panned, or krpano has altered lookat 
     hOffset += hSpeed; 
     vOffset += vSpeed; 

     // Clamp vOffset 
     if (Math.abs(pitch + vOffset) > 90) { 
      vOffset = (pitch + vOffset > 0) ? (90 - pitch) :(-90 - pitch) 
     } 

     hLookAt = wrapAngle(-yaw - 180 + hOffset); 
     vLookAt = Math.max(Math.min((pitch + vOffset), 90), -90); 

     // Dampen lookat 
     if (Math.abs(hLookAt - hLookAtNow) > 180) { 
      hLookAtNow += (hLookAt > hLookAtNow) ? 360 :-360; 
     } 

     hLookAt = (1 - friction) * hLookAt + friction * hLookAtNow; 
     vLookAt = (1 - friction) * vLookAt + friction * vLookAtNow; 

     if (Math.abs(camRoll - camRollNow) > 180) { 
      camRollNow += (camRoll > camRollNow) ? 360 :-360; 
     } 

     camRoll = (1 - friction) * camRoll + friction * camRollNow; 

     var wAh:Number = wrapAngle(hLookAt); 
     Pano.instance.panoGyroChange(wAh, vLookAt); 
     //krpano.view.camroll = wrapAngle(camRoll); 

     if (vOffset != 0 && vElasticity > 0) { 
      if (vSpeed == 0) { 
       if (vElasticity == 1) { 
        vOffset = 0; 
        vElasticSpeed = 0; 
       } else { 
        // vElasticSpeed = 1 - ((1 - vElasticSpeed) * krpano.control.touchfriction); 
        vOffset *= 1 - (Math.pow(vElasticity, 2) * vElasticSpeed); // use Math.pow to be able to use saner values 

        if (Math.abs(vOffset) < 0.1) { 
         vOffset = 0; 
         vElasticSpeed = 0; 
        } 
       } 
      } else { 
       vElasticSpeed = 0; 
      } 
     } 
    } 

    private function rotateEuler(euler:Object):Object { 
     // This function is based on http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm 
     // and http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToEuler/index.htm 
     trace(euler); 
     var heading:Number; 
     var bank:Number; 
     var attitude:Number; 
     var ch:Number = Math.cos(euler.yaw); 
     var sh:Number = Math.sin(euler.yaw); 
     var ca:Number = Math.cos(euler.pitch); 
     var sa:Number = Math.sin(euler.pitch); 
     var cb:Number = Math.cos(euler.roll); 
     var sb:Number = Math.sin(euler.roll); 

     var matrix:Array = [ 
      sh * sb - ch * sa * cb, -ch * ca, ch * sa * sb + sh * cb, 
      ca * cb, -sa, -ca * sb, 
      sh * sa * cb + ch * sb, sh * ca, -sh * sa * sb + ch * cb 
     ]; // Note:Includes 90 degree rotation around z axis 

     /* [m00 m01 m02] 0 1 2 
     * [m10 m11 m12] 3 4 5 
     * [m20 m21 m22] 6 7 8 */ 

     if (matrix[3] > 0.9999) { 
      // Deal with singularity at north pole 
      heading = Math.atan2(matrix[2], matrix[8]); 
      attitude = Math.PI/2; 
      bank = 0; 
     } else if (matrix[3] < -0.9999) { 
      // Deal with singularity at south pole 
      heading = Math.atan2(matrix[2], matrix[8]); 
      attitude = -Math.PI/2; 
      bank = 0; 
     } else { 
      heading = Math.atan2(-matrix[6], matrix[0]); 
      bank = Math.atan2(-matrix[5], matrix[4]); 
      attitude = Math.asin(matrix[3]); 
     } 

     return { 
      yaw:heading, 
      pitch:attitude, 
      roll:bank 
     }; 
    } 

    private function wrapAngle(value:Number):Number { 
     value = value % 360; 
     return (value <= 180) ? value :value - 360; 
    } // wrap a value between -180 and 180 
    //function stringToBoolean(value:Number):String 
    //{ return (String("yesontrue1").indexOf(String(value:Number)) >= 0) }; 
} 
+0

我發現怎麼別人已經在JavaScript中做了一個例子,我剛剛去如何把它轉換成AS3 https://github.com/fieldOfView/krpano_fovplugins/blob/master/不知道陀螺儀/源/ gyro.source.js – user5839

回答

0

沒有你的程序的其餘部分,我將無法編譯這個,但我已經糾正了我能找到的語法錯誤。也就是說,如果你可以用JS或As3編程,你應該能夠遵循邏輯並編寫你自己的類(它們都是EMCAScript)。繼續追求,直到你遇到一個比「不行」更穩定的問題(這通常是一個沒有人願意回答的問題)。

private var isTopAccessible:Boolean = false; 
private var isDeviceAvailable:Boolean; 
private var isEnabled:Boolean = false; 
private var vElasticity:Number = 0; 
private var isVRelative:Boolean = false; 
private var isCamRoll:Boolean = false; 
private var friction:Number = 0.5; 
private var isTouching:Boolean = false; 
private var validSample:Boolean = false; 
private var firstSample:* = null; 
private var hOffset:Number = 0; 
private var vOffset:Number = 0; 
private var hLookAt:Number = 0; 
private var vLookAt:Number = 0; 
private var camRoll:Number = 0; 
private var vLookAtNow:Number = 0; 
private var hLookAtNow:Number = 0; 
private var hSpeed:Number = 0; 
private var vSpeed:Number = 0; 
private var vElasticSpeed:Number = 0; 
private var camRollNow:Number; 
private var pitch:Number; 
private var yaw:Number; 
private var altYaw:Number; 
private var factor:Number; 
private var degRad:Number = Math.PI/180; 

public function handleDeviceOrientation(x:Number, y:Number):void { 
    // Process event.alpha, event.beta and event.gamma 
    var orientation:* = rotateEuler({ 
     "yaw":y * degRad, 
     "pitch":x * degRad, 
     "roll":0 
    }); 
    yaw = wrapAngle(orientation.yaw/degRad); 
    pitch = orientation.pitch/degRad; 
    altYaw = yaw, factor; 
    hLookAtNow = Pano.instance.pan; 
    vLookAtNow = Pano.instance.tilt; 
    hSpeed = hLookAtNow - hLookAt, 
    vSpeed = vLookAtNow - vLookAt; 

    // Ignore all sample until we get a sample that is different from the first sample 
    if (!validSample) { 
     if (firstSample == null) { 
      firstSample = orientation; 
     } else { 
      if (orientation.yaw != firstSample.yaw || orientation.pitch != firstSample.pitch || orientation.roll != firstSample.roll) { 
       firstSample = null; 
       validSample = true; 
       if (isVRelative) { 
        vOffset = -pitch; 
       } 
      } 
     } 
     return; 
    } 

    // Fix gimbal lock 
    if (Math.abs(pitch) > 70) { 
     altYaw = y; 

     /*switch(deviceOrientation) { 
      case 0: 
       if (pitch>0) 
       altYaw += 180; 
       break; 
      case 90: 
       altYaw += 90; 
       break; 
      case -90: 
       altYaw += -90; 
       break; 
      case 180: 
       if (pitch<0) 
       altYaw += 180; 
       break; 
     }*/ 

     var altYaw:Number = wrapAngle(altYaw); 
     if (Math.abs(altYaw - yaw) > 180) { 
      altYaw += (altYaw < yaw) ? 360 :-360; 
     } 

     var factor:Number = Math.min(1, (Math.abs(pitch) - 70)/10); 
     yaw = yaw * (1 - factor) + altYaw * factor; 

     //camRoll *= (1 - factor); 
    } 

    // Track view change since last orientation event 
    // ie:user has manually panned, or krpano has altered lookat 
    hOffset += hSpeed; 
    vOffset += vSpeed; 

    // Clamp vOffset 
    if (Math.abs(pitch + vOffset) > 90) { 
     vOffset = (pitch + vOffset > 0) ? (90 - pitch) :(-90 - pitch) 
    } 

    hLookAt = wrapAngle(-yaw - 180 + hOffset); 
    vLookAt = Math.max(Math.min((pitch + vOffset), 90), -90); 

    // Dampen lookat 
    if (Math.abs(hLookAt - hLookAtNow) > 180) { 
     hLookAtNow += (hLookAt > hLookAtNow) ? 360 :-360; 
    } 

    hLookAt = (1 - friction) * hLookAt + friction * hLookAtNow; 
    vLookAt = (1 - friction) * vLookAt + friction * vLookAtNow; 

    if (Math.abs(camRoll - camRollNow) > 180) { 
     camRollNow += (camRoll > camRollNow) ? 360 :-360; 
    } 

    camRoll = (1 - friction) * camRoll + friction * camRollNow; 

    var wAh:Number = wrapAngle(hLookAt); 
    Pano.instance.panoGyroChange(wAh, vLookAt); 
    //krpano.view.camroll = wrapAngle(camRoll); 

    if (vOffset != 0 && vElasticity > 0) { 
     if (vSpeed == 0) { 
      if (vElasticity == 1) { 
       vOffset = 0; 
       vElasticSpeed = 0; 
      } else { 
       // vElasticSpeed = 1 - ((1 - vElasticSpeed) * krpano.control.touchfriction); 
       vOffset *= 1 - (Math.pow(vElasticity, 2) * vElasticSpeed); // use Math.pow to be able to use saner values 

       if (Math.abs(vOffset) < 0.1) { 
        vOffset = 0; 
        vElasticSpeed = 0; 
       } 
      } 
     } else { 
      vElasticSpeed = 0; 
     } 
    } 
} 

private function rotateEuler(euler:Object):Object { 
    // This function is based on http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm 
    // and http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToEuler/index.htm 
    trace(euler); 
    var heading:Number; 
    var bank:Number; 
    var attitude:Number; 
    var ch:Number = Math.cos(euler.yaw); 
    var sh:Number = Math.sin(euler.yaw); 
    var ca:Number = Math.cos(euler.pitch); 
    var sa:Number = Math.sin(euler.pitch); 
    var cb:Number = Math.cos(euler.roll); 
    var sb:Number = Math.sin(euler.roll); 

    var matrix:Array = [ 
     sh * sb - ch * sa * cb, -ch * ca, ch * sa * sb + sh * cb, 
     ca * cb, -sa, -ca * sb, 
     sh * sa * cb + ch * sb, sh * ca, -sh * sa * sb + ch * cb 
    ]; // Note:Includes 90 degree rotation around z axis 

    /* [m00 m01 m02] 0 1 2 
    * [m10 m11 m12] 3 4 5 
    * [m20 m21 m22] 6 7 8 */ 

    if (matrix[3] > 0.9999) { 
     // Deal with singularity at north pole 
     heading = Math.atan2(matrix[2], matrix[8]); 
     attitude = Math.PI/2; 
     bank = 0; 
    } else if (matrix[3] < -0.9999) { 
     // Deal with singularity at south pole 
     heading = Math.atan2(matrix[2], matrix[8]); 
     attitude = -Math.PI/2; 
     bank = 0; 
    } else { 
     heading = Math.atan2(-matrix[6], matrix[0]); 
     bank = Math.atan2(-matrix[5], matrix[4]); 
     attitude = Math.asin(matrix[3]); 
    } 

    return { 
     yaw:heading, 
     pitch:attitude, 
     roll:bank 
    }; 
} 

private function wrapAngle(value:Number):Number { 
    value = value % 360; 
    return (value <= 180) ? value :value - 360; 
} // wrap a value between -180 and 180 
//function stringToBoolean(value:Number):String 
//{ return (String("yesontrue1").indexOf(String(value:Number)) >= 0) }; 
+0

感謝您解決這部分。其實我是過度複雜它和我需要的所有\t \t公共靜態函數toDegrees(弧度:數字):Number { \t \t \t return(radians * 180/Math.PI); \t \t} – user5839