【发布时间】:2014-02-12 00:36:07
【问题描述】:
我正在尝试添加数学以控制带有陀螺仪的全景图并且正在苦苦挣扎。这是一个内置在 AS3 中的移动应用程序。
我得到了来自陀螺仪的数据(x 和 y),并且得到了当前角度(平移和倾斜)。我想要做的是根据来自陀螺仪的数据用新的角度更新 cameraController。
我一直在尝试将我在 https://github.com/fieldOfView/krpano_fovplugins/blob/master/gyro/source/gyro.source.js 上找到的 Javascript 转换为 Actionscript 3,它有点工作 - 但不是真的。
编辑
感谢我尝试了这些更改并添加了相机回滚,因为欧拉数学需要它,它运行但数学有问题。
全景图似乎只是向上和向左移动,在将手机向另一方向移动一段时间后它会向下移动,然后向右移动。
您能看到我在 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) };
}
【问题讨论】:
-
我找到了一个其他人如何在 javascript 中完成它的示例,我只是不知道如何在 AS3 中转换它github.com/fieldOfView/krpano_fovplugins/blob/master/gyro/…
标签: actionscript-3 math mobile air gyroscope