diff --git a/gyro/source/gyro.source.js b/gyro/source/gyro.source.js index c7d543d..4b06c1c 100644 --- a/gyro/source/gyro.source.js +++ b/gyro/source/gyro.source.js @@ -1,20 +1,20 @@ /* gyro plugin for KRPanoJS and iOS4.2+ by Aldo Hoeben / fieldOfView.com -contributions by +with contributions by Sjeiti / ronvalstar.nl Klaus / krpano.com - + http://fieldofview.github.com/krpano_fovplugins/gyro/plugin.html This software can be used free of charge and the source code is available under a Creative Commons Attribution license: - http://creativecommons.org/licenses/by/3.0/ + http://creativecommons.org/licenses/by/3.0/ */ var krpanoplugin = function() { var local = this, krpano = null, plugin = null, - + isDeviceAvailable, isEnabled = false, vElasticity = 0, @@ -22,73 +22,73 @@ var krpanoplugin = function() friction = 0.5, isTouching = false, - hOffset = 0, vOffset = 0, + hOffset = 0, vOffset = 0, hLookAt = 0, vLookAt = 0, camRoll = 0, vElasticSpeed = 0, - + degRad = Math.PI/180; //////////////////////////////////////////////////////////// // plugin management - + local.registerplugin = function(krpanointerface, pluginpath, pluginobject) { krpano = krpanointerface; plugin = pluginobject; - + if (krpano.version < "1.0.8.14" || krpano.build < "2011-03-30") { krpano.trace(3,"gyro plugin - too old krpano version (min. 1.0.8.14)"); return; } - // initiate device check + // Initiate device check if(!!window.DeviceOrientationEvent) window.addEventListener("deviceorientation", handleDeviceCheck); - - // register attributes + + // Register attributes plugin.registerattribute("available",false, function(arg){}, function(){ return isDeviceAvailable; }); plugin.registerattribute("enabled", true, function(arg){ stringToBoolean(arg) ? enable() : disable() }, function(){ return isEnabled; }); - plugin.registerattribute("velastic", 0, function(arg){ vElasticity = Math.max(Math.min(Number(arg), 1), 0); krpano.trace(0,(1-Math.pow(vElasticity,2))); }, function() { return vElasticity; }); + plugin.registerattribute("velastic", 0, function(arg){ vElasticity = Math.max(Math.min(Number(arg), 1), 0); krpano.trace(0,(1-Math.pow(vElasticity,2))); }, function() { return vElasticity; }); plugin.registerattribute("camroll", false, function(arg){ isCamRoll = stringToBoolean(arg); }, function() { return isCamRoll; }); plugin.registerattribute("friction", 0.5, function(arg){ friction = Math.max(Math.min(Number(arg), 1), 0); }, function() { return friction; }); - - // register methods + + // Register methods plugin.enable = enable; plugin.disable = disable; plugin.toggle = toggle; } - - + + local.unloadplugin = function() { window.removeEventListener("deviceorientation", handleDeviceCheck); disable(); - + plugin = null; krpano = null; } - - + + //////////////////////////////////////////////////////////// // public methods - + function enable() { - if (isDeviceAvailable === undefined) + if (isDeviceAvailable === undefined) { isEnabled = true; return; - } - + } + if (isDeviceAvailable && !isEnabled) { - window.addEventListener("deviceorientation", handleDeviceOrientation, true); + window.addEventListener("deviceorientation", handleDeviceOrientation, true); krpano.control.layer.addEventListener("touchstart", handleTouchStart, true); - krpano.control.layer.addEventListener("touchend", handleTouchEnd, true); - krpano.control.layer.addEventListener("touchcancel", handleTouchEnd, true); + krpano.control.layer.addEventListener("touchend", handleTouchEnd, true); + krpano.control.layer.addEventListener("touchcancel", handleTouchEnd, true); isEnabled = true; - + hOffset = -top.orientation; vOffset = 0; hLookAt = 0; @@ -106,13 +106,13 @@ var krpanoplugin = function() { window.removeEventListener("deviceorientation", handleDeviceOrientation); krpano.control.layer.removeEventListener("touchstart", handleTouchStart); - krpano.control.layer.removeEventListener("touchend", handleTouchEnd); - krpano.control.layer.removeEventListener("touchcancel", handleTouchEnd); + krpano.control.layer.removeEventListener("touchend", handleTouchEnd); + krpano.control.layer.removeEventListener("touchcancel", handleTouchEnd); } isEnabled = false; } - + function toggle() { if(isEnabled) @@ -120,25 +120,25 @@ var krpanoplugin = function() else enable(); } - + //////////////////////////////////////////////////////////// - // private methods - + // private methods + function handleDeviceCheck(event) { - // deviceorientation events are being generated + // Confirm that deviceorientation events are being generated isDeviceAvailable = true; window.removeEventListener("deviceorientation", handleDeviceCheck); - // if this event came after any event that set the "enabled" property, call enable() now - if(isEnabled) + // If this event came after any event that set the "enabled" property, call enable() now + if(isEnabled) { isEnabled = false; enable(); } } - + function handleTouchStart(event) { isTouching = true; @@ -146,18 +146,18 @@ var krpanoplugin = function() function handleTouchEnd(event) { - isTouching = false; + isTouching = false; } - + function handleDeviceOrientation(event) { if ( !isTouching && isEnabled ) { - // process event.alpha, event.beta and event.gamma - var orientation = rotateEuler( new Object( { - yaw: event["alpha"] * degRad, - pitch: event["beta"] * degRad, - roll: event["gamma"] * degRad + // Process event.alpha, event.beta and event.gamma + var orientation = rotateEuler( new Object( { + yaw: event["alpha"] * degRad, + pitch: event["beta"] * degRad, + roll: event["gamma"] * degRad } ) ), yaw = wrapAngle( orientation.yaw / degRad ), pitch = orientation.pitch / degRad, @@ -172,72 +172,72 @@ var krpanoplugin = function() if(isCamRoll) { camRoll = wrapAngle( 180 + Number(top.orientation) - orientation.roll / degRad ); } - - // fix gimbal lock + + // Fix gimbal lock if( Math.abs(pitch) > 70 ) { - altYaw = event.alpha; - + altYaw = event.alpha; + switch(top.orientation) { case 0: - if ( pitch>0 ) + if ( pitch>0 ) altYaw += 180; break; - case 90: + case 90: altYaw += 90; break; - case -90: + case -90: altYaw += -90; break; case 180: - if ( pitch<0 ) + if ( pitch<0 ) altYaw += 180; break; } - + altYaw = wrapAngle(altYaw); - if( Math.abs( altYaw - yaw ) > 180 ) + if( Math.abs( altYaw - yaw ) > 180 ) altYaw += ( altYaw < yaw ) ? 360 : -360; - + factor = Math.min( 1, ( Math.abs( pitch ) - 70 ) / 10 ); yaw = yaw * (1 - factor) + altYaw * factor; - + camRoll *= (1 - factor); } - - // track view change since last orientation event + + // Track view change since last orientation event // ie: user has manually panned, or krpano has altered lookat hOffset += hSpeed; vOffset += vSpeed; - - // clamp vOffset + + // 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) + // 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) + + if(Math.abs(camRoll - camRollNow) > 180) camRollNow += (camRoll > camRollNow)?360:-360; camRoll = (1-friction)*camRoll + friction*camRollNow; - + krpano.view.hlookat = wrapAngle(hLookAt); krpano.view.vlookat = vLookAt; krpano.view.camroll = wrapAngle(camRoll); - - if( vOffset != 0 && vElasticity > 0 ) + + if( vOffset != 0 && vElasticity > 0 ) { if( vSpeed == 0) { - if( vElasticity == 1) + if( vElasticity == 1) { vOffset = 0; vElasticSpeed = 0; @@ -246,22 +246,22 @@ var krpanoplugin = function() { 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; - } + } } } - + function rotateEuler( euler ) { - // based on http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/index.htm + // 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 var heading, bank, attitude, @@ -272,28 +272,28 @@ var krpanoplugin = function() cb = Math.cos(euler.roll), sb = Math.sin(euler.roll); - // note: includes 90 degree rotation around z axis + // Note: Includes 90 degree rotation around z axis matrix = new Array - ( + ( sh*sb - ch*sa*cb, -ch*ca, ch*sa*sb + sh*cb, - ca*cb, -sa, -ca*sb, + ca*cb, -sa, -ca*sb, sh*sa*cb + ch*sb, sh*ca, -sh*sa*sb + ch*cb ); - + /* [m00 m01 m02] 0 1 2 - * [m10 m11 m12] 3 4 5 + * [m10 m11 m12] 3 4 5 * [m20 m21 m22] 6 7 8 */ - + if (matrix[3] > 0.9999) - { - // singularity at north pole + { + // 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) - { - // singularity at south pole + } + 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; @@ -304,13 +304,13 @@ var krpanoplugin = function() bank = Math.atan2(-matrix[5],matrix[4]); attitude = Math.asin(matrix[3]); } - - return new Object( { yaw:heading, pitch:attitude, roll:bank } ) + + return new Object( { yaw:heading, pitch:attitude, roll:bank } ) } //////////////////////////////////////////////////////////// // utility functions - + function wrapAngle(value) { value = value % 360; return (value<=180)? value : value-360; } // wrap a value between -180 and 180 function stringToBoolean(value) { return (String("yesontrue1").indexOf( String(value).toLowerCase() ) >= 0); }; // boolean cast helper function } \ No newline at end of file