Limit camera rotation angle around target entity in model viewer

Hi guys, im sorry for the dumb qustion but i cant wrap my head aroound it.

Is very simple, i whant to limit the angle in whitch the camera can move, when locked on the center cube in the scene. As i i whanted to let the user see only some faces of the lateral cube, but not the backfaces.

I guees that the property to limit is the YAW. Using a mathClamp function. Still no luck

Can you help me? Thanks.

Hi @Sasa_Olmedo,

If you create a new project based on the model viewer template, you will get the orbit-camera.js script included automatically.

On that script there is already a min/max limit for Pitch, as you guessed using math.clamp. Study that script to see how it’s implemented.

image

1 Like

i try to replicate the function adding a few new attributes

OrbitCamera.prototype._clampYawAngle = function (yaw) {
// Negative due as the pitch is inversed since the camera is orbiting the entity
return pc.math.clamp(yaw, -this.rotationAngleMax, -this.rotationAngleMin);

};

no luck using this function, do you have any idea ?

Hi @Sasa_Olmedo,

Here is how I did it, it’s a lot of small additions so follow closely:

// added two new attributes
OrbitCamera.attributes.add('yawAngleMax', {type: 'number', default: 90, title: 'Yaw Angle Max (degrees)'});
OrbitCamera.attributes.add('yawAngleMin', {type: 'number', default: -90, title: 'Yaw Angle Min (degrees)'});

Added a new property getter/setter:

// Property to get and set the yaw of the camera around the pivot point (degrees)
Object.defineProperty(OrbitCamera.prototype, "yaw", {
    get: function() {
        return this._targetYaw;
    },

    set: function(value) {
        this._targetYaw = this._clampYawAngle(value);
    }
});

Added this in the initialize method:

this._yaw = this._calcYaw(cameraQuat);
this._targetYaw = this._yaw;

Include it in the update(dt) method:

        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();

And finally in the _updatePosition() method:

this.entity.setLocalEulerAngles(this._pitch, this._yaw, 0);

And the methods used:

OrbitCamera.prototype._calcYaw = function (quat) {
    var transformedForward = new pc.Vec3();
    quat.transformVector(pc.Vec3.FORWARD, transformedForward);

    return Math.atan2(-transformedForward.x, -transformedForward.z) * pc.math.RAD_TO_DEG;
};

OrbitCamera.prototype._clampYawAngle = function (yaw) {
    
    if( this.yawAngleMax === 0 && this.yawAngleMin === 0 ){
        return yaw;
    }else{
        return pc.math.clamp(yaw, -this.yawAngleMax, -this.yawAngleMin);   
    }
};
2 Likes