Camera Control by mobile device gyroscope

Hi there!

Im trying to create a camera control by mobile device gyroscope - basically i want to look around (the camera position is fixed) - does somebody has an hint about the best practise to achieve this?

I have the following apporach but the camera isnt orientating correctly…

var GyroscopeLook = pc.createScript('gyroscopeLook');

// Initialize code called once per entity
GyroscopeLook.prototype.initialize = function() {
    var self = this;

    this.alpha = 0; // Rotation around Z-axis
    this.beta = 0;  // Rotation around X-axis
    this.gamma = 0; // Rotation around Y-axis

    // Check if the device has a gyroscope and is mobile
    if (window.DeviceOrientationEvent && pc.platform.mobile) {
        console.log("Gyroscope detected. Listening for device orientation...");
        window.addEventListener("deviceorientation", function(event) {
            self.alpha = event.alpha;  // Compass direction
            self.beta = event.beta;    // Tilt front-to-back
            self.gamma = event.gamma;  // Tilt left-to-right
        }, true);

        this.so = window.orientation || 0;
        window.addEventListener('orientationchange', function() {
            self.so = window.orientation || 0;
        }, false);
    } else {
        console.log("Gyroscope not detected or not on a mobile platform.");
    }
};

// Update code called every frame
GyroscopeLook.prototype.update = function(dt) {
    if (window.DeviceOrientationEvent && pc.platform.mobile) {
        // Convert degrees to radians
        var alpha = pc.math.DEG_TO_RAD * this.alpha;
        var beta = pc.math.DEG_TO_RAD * this.beta;
        var gamma = pc.math.DEG_TO_RAD * this.gamma;

        // Calculate quaternion from Euler angles
        var quaternion = new pc.Quat();

        // Apply rotations
        quaternion.setFromEulerAngles(beta, alpha, -gamma);

        // Update the camera's rotation
        this.entity.setLocalRotation(quaternion);

        console.log("Camera rotation applied: ", this.entity.getLocalRotation());
    }
};




/*
// Initialize code called once per entity
GyroscopeLook.prototype.initialize = function() {
    var self = this;

    this.alpha = 0;
    this.beta = 90;
    this.gamma = 0;

    // Check if the device has a gyroscope and is mobile
    if (window.DeviceOrientationEvent && pc.platform.mobile) {
        console.log("Gyroscope detected. Listening for device orientation...");
        window.addEventListener("deviceorientation", function(event) {
            self.alpha = event.alpha;
            self.beta = event.beta;
            self.gamma = event.gamma;
            console.log("Alpha: " + self.alpha + " | Beta: " + self.beta + " | Gamma: " + self.gamma);
        }, true);

        this.so = window.orientation || 0;
        window.addEventListener('orientationchange', function() {
            self.so = window.orientation || 0;
        }, false);
    } else {
        console.log("Gyroscope not detected or not on a mobile platform.");
    }

    this.jzQ = pc.Quat.IDENTITY.clone();
    this.www = true;
};

// Update code called every frame
GyroscopeLook.prototype.update = function(dt) {
    if (window.DeviceOrientationEvent && pc.platform.mobile) {
        var x = pc.math.DEG_TO_RAD * this.beta;
        var y = pc.math.DEG_TO_RAD * this.gamma;
        var z = pc.math.DEG_TO_RAD * -this.alpha;

        var c1 = Math.cos(x / 2);
        var c2 = Math.cos(y / 2);
        var c3 = Math.cos(z / 2);
        var s1 = Math.sin(x / 2);
        var s2 = Math.sin(y / 2);
        var s3 = Math.sin(z / 2);

        var q0 = new pc.Quat(
            s1 * c2 * c3 + c1 * s2 * s3,
            c1 * s2 * c3 - s1 * c2 * s3,
            c1 * c2 * s3 - s1 * s2 * c3,
            c1 * c2 * c3 + s1 * s2 * s3
        );

        // Apply orientation adjustment
        var q1 = new pc.Quat();
        q1.setFromEulerAngles(0, 90, 0); // Adjust the rotation to correct the camera looking up
        q0.mul(q1);

        var q2 = new pc.Quat();
        q2.setFromAxisAngle(pc.Vec3.FORWARD, this.so);
        q0.mul(q2);

        if (this.www) { // Reset gyroscope offset when initialized
            this.www = false;
            this.jzQ = q0.clone();
            this.jzQ.invert();
        }

        this.entity.setLocalRotation(q0.mul(this.jzQ));
        console.log("Camera rotation applied.");
    }
};


/*
// Initialize code called once per entity
GyroscopeLook.prototype.initialize = function() {
    var self = this;

    this.alpha = 0;
    this.beta = 90;
    this.gamma = 90;

    // Check if the device has a gyroscope and is mobile
    if (window.DeviceOrientationEvent && pc.platform.mobile) {
        console.log("Gyroscope detected. Listening for device orientation...");
        window.addEventListener("deviceorientation", function(event) {
            self.alpha = event.alpha;
            self.beta = event.beta;
            self.gamma = event.gamma;
            console.log("Alpha: " + self.alpha + " | Beta: " + self.beta + " | Gamma: " + self.gamma);
        }, true);

        this.so = window.orientation || 0;
        window.addEventListener('orientationchange', function() {
            self.so = window.orientation || 0;
        }, false);
    } else {
        console.log("Gyroscope not detected or not on a mobile platform.");
    }

    this.jzQ = pc.Quat.IDENTITY.clone();
    this.www = true;
};

// Update code called every frame
GyroscopeLook.prototype.update = function(dt) {
    if (window.DeviceOrientationEvent && pc.platform.mobile) {
        var x = pc.math.DEG_TO_RAD * this.beta;
        var y = pc.math.DEG_TO_RAD * this.gamma;
        var z = pc.math.DEG_TO_RAD * -this.alpha;

        var c1 = Math.cos(x / 2);
        var c2 = Math.cos(y / 2);
        var c3 = Math.cos(z / 2);
        var s1 = Math.sin(x / 2);
        var s2 = Math.sin(y / 2);
        var s3 = Math.sin(z / 2);

        var q0 = new pc.Quat(
            s1 * c2 * c3 + c1 * s2 * s3,
            c1 * s2 * c3 - s1 * c2 * s3,
            c1 * c2 * s3 - s1 * s2 * c3,
            c1 * c2 * c3 + s1 * s2 * s3
        );

        // Apply orientation adjustment
        var q1 = new pc.Quat();
        q1.setFromEulerAngles(90, 0, 0); // Adjust the rotation to correct the camera looking up
        q0.mul(q1);

        var q2 = new pc.Quat();
        q2.setFromAxisAngle(pc.Vec3.FORWARD, this.so);
        q0.mul(q2);

        if (this.www) { // Reset gyroscope offset when initialized
            this.www = false;
            this.jzQ = q0.clone();
            this.jzQ.invert();
        }

        this.entity.setLocalRotation(q0.mul(this.jzQ));
        console.log("Camera rotation applied.");
    }
};
*/

/*
var GyroscopeLook = pc.createScript('gyroscopeLook');

// Initialize code called once per entity
GyroscopeLook.prototype.initialize = function() {
    var self = this;

    this.alpha = 0;
    this.beta = 0;
    this.gamma = 0;

    // Check if the device has a gyroscope and is mobile
    if (window.DeviceOrientationEvent && pc.platform.mobile) {
        console.log("Gyroscope detected. Listening for device orientation...");
        window.addEventListener("deviceorientation", function(event) {
            self.alpha = event.alpha;
            self.beta = event.beta;
            self.gamma = event.gamma;
            console.log("Alpha: " + self.alpha + " | Beta: " + self.beta + " | Gamma: " + self.gamma);
        }, true);

        this.so = window.orientation || 0;
        window.addEventListener('orientationchange', function() {
            self.so = window.orientation || 0;
        }, false);
    } else {
        console.log("Gyroscope not detected or not on a mobile platform.");
    }

    this.jzQ = pc.Quat.IDENTITY.clone();
    this.www = true;
};

// Update code called every frame
GyroscopeLook.prototype.update = function(dt) {
    if (window.DeviceOrientationEvent && pc.platform.mobile) {
        var x = pc.math.DEG_TO_RAD * this.beta;
        var y = pc.math.DEG_TO_RAD * this.alpha;
        var z = pc.math.DEG_TO_RAD * -this.gamma;

        var c1 = Math.cos(x / 2);
        var c2 = Math.cos(y / 2);
        var c3 = Math.cos(z / 2);
        var s1 = Math.sin(x / 2);
        var s2 = Math.sin(y / 2);
        var s3 = Math.sin(z / 2);

        var q0 = new pc.Quat(
            s1 * c2 * c3 + c1 * s2 * s3,
            c1 * s2 * c3 - s1 * c2 * s3,
            c1 * c2 * s3 - s1 * s2 * c3,
            c1 * c2 * c3 + s1 * s2 * s3
        );

        // Apply orientation adjustment
        var q1 = new pc.Quat();
        q1.setFromEulerAngles(0, 0, -90); // Adjust the rotation to correct the camera looking up
        q0.mul(q1);

        var q2 = new pc.Quat();
        q2.setFromAxisAngle(pc.Vec3.FORWARD, this.so);
        q0.mul(q2);

        if (this.www) { // Reset gyroscope offset when initialized
            this.www = false;
            this.jzQ = q0.clone();
            this.jzQ.invert();
        }

        this.entity.setLocalRotation(q0.mul(this.jzQ));
        console.log("Camera rotation applied.");
    }
};
*/

Or maybe someone has found a script for this case? Basically i would need a script to just look around in an 360 degree scene

This post has some info about that.

[SOLVED] Device Rotation (alpha, beta, gamma) vs. Euler Angles - Help & Support - PlayCanvas Discussion

1 Like

Hi Nelson,

thanks for your answer - right now i could not figure out how to get a simple camera look script via gyroscope.

@yaustar
I saw, that you had some posts regarding this topic. Do you know if there is any script or reference for this? When trying to look around with the gyroscope i think you just need the beta / gamma axis, because the roll of the alpha axis isnt necessary (but not sure). I searched the internet for a simple excample but could not find anything to bring this to work in playcanvas :frowning:

I don’t remember a project that has a look about camera via phone rotation. The other thread has a project that uses the phone rotation for something else that you could try to modify

Hi @yaustar ,

I think i it works now :slight_smile:

Thank you very much for your effort in all posts! :slight_smile:

Hi @Question2u , have you had success manipulating the camera rotation with the orientation of the phone? If so, would it be possible to share the example code, I’m looking for that.