Camera Transition and Orbit Camera Issue

I want to apply the orbitCamera and camera transition (using slerp and lerp) together.

below is transition camera code

var TransitionCamera = pc.createScript("transitionCamera");
TransitionCamera.attributes.add("duration", {
    type: "number",
    default: 5,
    title: "Duration (Secs)",
});
TransitionCamera.prototype.initialize = function () {
    this.time = 0;
};
TransitionCamera.prototype.update = function (dt) {
    this.app.on("camera:transition", (target) => {
        var targetEntity = this.app.root.findByName(target);
        this.startRotation = this.entity.getRotation();
        this.startPosition = this.entity.getPosition();
        this.endRotation = target.getRotation();
        this.endPosition = targetEntity.getPosition();
        this.time = 0;
    });

    this.time += dt * 2;
    if (this.time > this.duration) {
        this.time -= this.duration;
    }
    ;
    var alpha = this.time / this.duration;
    entityRotation = this.entity.getRotation();
    entityPosition = this.entity.getPosition();
    if (this.startRotation && this.startPosition) {
        entityRotation.slerp(this.startRotation, this.endRotation, alpha);
    }
    if (this.endPosition && this.endRotation) {
        entityPosition.lerp(this.startPosition, this.endPosition, alpha);
    }
    this.entity.setRotation(entityRotation);
    this.entity.setPosition(entityPosition);

    if (this.startPosition && this.endPosition) {
        // console.log(this.entity.getPosition().x, this.endPosition.x);
        if (this.entity.getPosition().x === this.endPosition.x) {
            console.log('Completed')
            // this.app.fire('camera:transitionComplete');

            var camera = this.app.root.findByName("Camera");
            camera.script.orbitCamera.enabled = true;
            camera.script.transitionCamera.enabled = false;
        }
    }
};

Somehow both can be applied together,so I disabled the orbitCamera then enable it again once after the transition is completed.

The problem is when the orbit camera is enabled, the camera position is changed based on orbitCamera setting.

Is there any better tip to integrate both of orbit camera and camera transition?

Hi @sooyong_Kim,

I don’t think the issue is in your code, but in the way the two scripts instances behave.

To achieve smooth transitions you need to make sure that when the orbit camera script is enabled it starts at the exact position and rotation where the transition script left the camera.

You may need to adjust the orbit camera script to be able to do a smooth short animation from that rotation towards the pivot point where it always looks, when the script is enabled.

1 Like

You might want to consider tweening your camera transitions:

Trouble with using look-around.js and tweening camera rotation together

It made things a lot easier for me.

1 Like

Before you enable it, there is a function on the script to set the position of the camera and the lookAt/pivot position:

// Useful if you have multiple viewing angles to swap between in a scene
OrbitCamera.prototype.resetAndLookAtPoint = function (resetPoint, lookAtPoint) {
    this.pivotPoint.copy(lookAtPoint);
    this.entity.setPosition(resetPoint);

    this.entity.lookAt(lookAtPoint);

    var distance = OrbitCamera.distanceBetween;
    distance.sub2(lookAtPoint, resetPoint);
    this.distance = distance.length();

    this.pivotPoint.copy(lookAtPoint);

    var cameraQuat = this.entity.getRotation();
    this.yaw = this._calcYaw(cameraQuat);
    this.pitch = this._calcPitch(cameraQuat, this.yaw);

    this._removeInertia();
    this._updatePosition();
};
2 Likes

I have simply changed the orbit camera update function as below.

OrbitCamera.prototype.update = function(dt) {

    this.app.on("camera:transition", (target) => {

        this.endPosition = new pc.Vec3(6.834090709686279, 1.9107747077941895, -1.2520310878753662 );

        this.time = 0;
    });

    // if (this.startRotation && this.startPosition && this.endRotation && this.endPosition) {
    if (this.endPosition) {
        this.resetAndLookAtPoint(this.endPosition, this.pivotPoint);

    } else {
        // Add inertia, if any
        var t = this.inertiaFactor === 0 ? 1 : Math.min(dt / this.inertiaFactor, 1);
        this._distance = pc.math.lerp(this._distance, this._targetDistance, t);
        this._yaw = pc.math.lerp(this._yaw, this._targetYaw, t);
        this._pitch = pc.math.lerp(this._pitch, this._targetPitch, t);
        this._updatePosition();
    }

};

If I trigger the event, the camera moved to the expected position. However, the mouse input stop working after the camera movement.

Can you kindly let me know what I have missed?

I have solved this issue and below is the code.

First time and duration variables should be set in init method.

    this.time = 0;
    this.duration = 5;
OrbitCamera.prototype.update = function(dt) {


    // Add inertia, if any
    var t = this.inertiaFactor === 0 ? 1 : Math.min(dt / this.inertiaFactor, 1);
    this._distance = pc.math.lerp(this._distance, this._targetDistance, t);
    this._yaw = pc.math.lerp(this._yaw, this._targetYaw, t);
    this._pitch = pc.math.lerp(this._pitch, this._targetPitch, t);

    this.app.on("camera:transition", (target) => {
        this.startPosition = this.entity.getPosition();
        this.endPosition = new pc.Vec3(target.x, target.y, target.z);
        this.time = 0;
    });

    if (this.startPosition && this.endPosition) {
        this.time += (dt * 1.5) ;
        if (this.time > this.duration) {
            this.time -= this.duration;
        }

        var alpha = this.time / this.duration;
        this.entityPosition = this.entity.getPosition();
        this.entityPosition.lerp(this.startPosition, this.endPosition, alpha);
        if(Math.round(this.endPosition.x * 10)/10  === Math.round(this.entityPosition.x *10 )/10
            && Math.round(this.endPosition.y *10)/10 === Math.round( this.entityPosition.y *10)/10
            && Math.round(this.endPosition.z * 10 ) / 10 === Math.round(this.entityPosition.z * 10) / 10) {
            console.log('Transition Completed');
            this.endPosition = null;
        } else {
            this.resetAndLookAtPoint(this.entityPosition, this.pivotPoint);
        }
    } else {
        this._updatePosition();
    }

};

It works fine.~!!!

1 Like