Jump to content

Camera Inertia Angle


Lary
 Share

Recommended Posts

Hi there,

Is there a way for me to get the ArcRotateCamera's rotation angle led by its inertia? 

I have pointerDown and pointerUp events to calculate how many angles I rotates during pointerEvent, but if I make a quick slide, the camera doesn't stop immediately after pointerUp, it will rotate for some angles due to inertia.

Thanks!

 

Link to comment
Share on other sites

3 minutes ago, Sebavan said:

I do not think that anything built in could provide the diff, but in your case if you prefer to have the full control yourself, you could stop inertia by putting to 0.

Hope that helps.

Thanks Sebavan, yes, putting the inertia to 0 could help. But the rotation would be so slow and would affect the UE, So I'm trying to calculate the inertia angle, it maybe something like camera inertia * pointerMove length. aha, just my imagination..Hope @Deltakosh and @Wingnut could support me any idea~

Link to comment
Share on other sites

You could rely on speed to make the camera faster independently of inertia.

Else about the formula  it is exactly computed like this:

if (this.inertialAlphaOffset !== 0 || this.inertialBetaOffset !== 0 || this.inertialRadiusOffset !== 0) {
let inertialAlphaOffset = this.inertialAlphaOffset;
if (this.beta <= 0) inertialAlphaOffset *= -1;
if (this.getScene().useRightHandedSystem) inertialAlphaOffset *= -1;
if (this.parent && this.parent._getWorldMatrixDeterminant() < 0) inertialAlphaOffset *= -1;
this.alpha += inertialAlphaOffset;
 
this.beta += this.inertialBetaOffset;
 
this.radius -= this.inertialRadiusOffset;
this.inertialAlphaOffset *= this.inertia;
this.inertialBetaOffset *= this.inertia;
this.inertialRadiusOffset *= this.inertia;
if (Math.abs(this.inertialAlphaOffset) < Epsilon)
this.inertialAlphaOffset = 0;
if (Math.abs(this.inertialBetaOffset) < Epsilon)
this.inertialBetaOffset = 0;
if (Math.abs(this.inertialRadiusOffset) < this.speed * Epsilon)
this.inertialRadiusOffset = 0;
}
 
where offset are computed from the pointers in this way:
if (pointA && pointB === null && cacheSoloPointer) {
if (this.panningSensibility !== 0 &&
((evt.ctrlKey && this.camera._useCtrlForPanning) || this._isPanClick)) {
this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / this.panningSensibility;
this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / this.panningSensibility;
} else {
var offsetX = evt.clientX - cacheSoloPointer.x;
var offsetY = evt.clientY - cacheSoloPointer.y;
this.camera.inertialAlphaOffset -= offsetX / this.angularSensibilityX;
this.camera.inertialBetaOffset -= offsetY / this.angularSensibilityY;
}
 
cacheSoloPointer.x = evt.clientX;
cacheSoloPointer.y = evt.clientY;
}
 
Hope this might help.
 
 
Link to comment
Share on other sites

Hi guys!  Interesting challenge.

Lary... after a click happens, CAN you pre-calculate the needed amount of camera.alpha change... to make the camera point-at the clicked point?  Maybe you could make a testing playground... and then we will try to find a formula to calculate that value.

IF you can, then perhaps animate the camera.alpha to the new angle.  Perhaps put the below function (untested) at the top of your code, which will add an ease-out camera.spin() function to all your created arcRotateCameras.  We are attaching a little animation motor to camera.alpha.

BABYLON.ArcRotateCamera.prototype.spin = function (radians, speed) {
     var ease = new BABYLON.CubicEase();
     ease.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEOUT);
     BABYLON.Animation.CreateAndStartAnimation('myanim', this, 'alpha', speed, 120, this.alpha, this.alpha+radians, 0, ease);
}

Reminder... I didn't test it.  :)  This playground has a bunch of little animation motors at the top of the code... added to abstractMesh.  They could work on cameras, too, after some adjusting.  You could make your animation be:    spin(amountOfChange)     ...or spinTo(newRadianValue).

EASEINOUT is also an option.

Just some Wingnut thoughts.  Might help.  Probably not.  :)

Link to comment
Share on other sites

var createScene = function () {

    // This creates a basic Babylon Scene object (non-mesh)
    var scene = new BABYLON.Scene(engine);

    // This creates and positions a free camera (non-mesh)
    var camera = new BABYLON.ArcRotateCamera("arcRotateCamera", 0, 0, 15, new BABYLON.Vector3(0, 0, 0), scene)
            camera.beta = Math.PI / 3;

    // This targets the camera to scene origin
    camera.setTarget(BABYLON.Vector3.Zero());

    // This attaches the camera to the canvas
    camera.attachControl(canvas, true);

    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
    var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);

    // Default intensity is 1. Let's dim the light a small amount
    light.intensity = 0.7;

    // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
    var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);

    // Move the sphere upward 1/2 its height
    sphere.position.y = 1;

    // Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
    var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);


    //Camera rotation Detection
    let oriAlpha = 0; 
        let oriBeta = 0; 
        let oriDirAlpha = 0; 
        let oriDirBeta = 0; 
        
        let turnAlpha = 0; 
        let turnBeta = 0; 
        
        let infoAlpha = [];
        let infoBeta = [];
        //
        // let camera = scene.activeCamera;
       
        let timeStart = null;
        scene.onPointerObservable.add(() => {
            
            oriAlpha = turnAlpha = camera.alpha;
            // console.log(oriAlpha)
            oriBeta = turnBeta = camera.beta;
            oriDirAlpha = 0;
            oriDirBeta = 0;
            infoAlpha = [];
            infoBeta = [];
            timeStart = new Date().getTime();
        }, 1)
        scene.onPointerObservable.add(() => {
            infoAlpha.push({
                dir: (camera.alpha - turnAlpha) > 0 ? 1 : -1,
                angle: camera.alpha - turnAlpha
            })

            if (infoAlpha.length === 1) {
                if (infoAlpha[0].angle === 0) {
                    console.log("click")
                } else {
                    var direction = infoAlpha[0].dir < 0 ? "Right:" : "Left:"
                   
                    console.log(direction + Math.abs(infoAlpha[0].angle * 180 / Math.PI).toFixed(0) + "°")
                }
            } else {
               
                var turns = infoAlpha.length;
                var turnInfo = "";

                for (var i = 0; i < turns; i++) {
                    var direction = infoAlpha[i].dir < 0 ? "Right:" : "Left:";
                    turnInfo += (direction + Math.abs(infoAlpha[i].angle * 180 / Math.PI).toFixed(0) + "°" + "\n")
                }
                console.log(turnInfo)
            }

            console.log("Duration:" + (new Date().getTime() - timeStart) / 1000 + "秒");
        }, 2)
        camera.onViewMatrixChangedObservable.add(() => {
            let alphaDif = camera.alpha - oriAlpha; 
            let betaDif = camera.beta - oriBeta;
            
            // console.log(alphaDif)
            oriAlpha = camera.alpha;
            oriBeta = camera.beta;

           
            if (alphaDif) {
                let dir = alphaDif > 0 ? 1 : -1; 
               
                if (!oriDirAlpha) {
                    oriDirAlpha = dir;
                    //   console.log(ariDirAlpha)
                } else {
                    //   console.log("turn:"+turnAlpha)
                   
                    if (oriDirAlpha !== dir) {
                        infoAlpha.push({
                            dir: oriDirAlpha,
                            angle: camera.alpha - turnAlpha
                        })
                        oriDirAlpha = dir;
                        turnAlpha = camera.alpha;
                    }
                }
            }

        })

    return scene;

};

Hi all, I paste my code here, coz I wonder if what happens that I can't save a PG for your information.

@Wingnut

Link to comment
Share on other sites

If all you're wanting is the additional angle that the camera will rotate due to inertia after the pointerup event, you can calculate it in radians as:

const additionalAngle = camera.inertialAlphaOffset / (1 - camera.inertia);

which follows from the implementation posted by Sebavan above.

http://playground.babylonjs.com/#PCMNE0#1

Link to comment
Share on other sites

5 hours ago, sable said:

If all you're wanting is the additional angle that the camera will rotate due to inertia after the pointerup event, you can calculate it in radians as:


const additionalAngle = camera.inertialAlphaOffset / (1 - camera.inertia);

which follows from the implementation posted by Sebavan above.

http://playground.babylonjs.com/#PCMNE0#1

Greeeeet! Thank you so sosososoos much Sable! It really saved me! I tested the values, and it is correct!!!!! 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...