# Need help with this mathematical problem between camera and orbitcontrols

Hi. this what I trying to solve:

My scene starts with:

*camera positions xyz set to: (0,10,30)
*Orbitcontrols target xyz set to: (0,10,0)

console.log(camera.position.distanceTo(controls.target) shows 30
So: the Distance between camera and target is 30

now the problem

this is what I want:

1.- *when distance between camera and target is >=20 orbit target postion.y and camera position.y will remains at 10
2.- *when distance between camera and target is ==10. target postion.y and camera position.y must be 15
3.- *when distance between camera and target is < 20. orbit target and camera will start to increse their position.y values until reach what I said in point two (15). in other words after < 20. target.y and camera position.y will increase in function of the decrease of distance.

I hope you understand me because I know my English is bad.

Any help will be appreciated

The math doesnâ€™t seem that complicated to me. What I gather from your description is the following:

• the camera is always looking horizontally (camera.y == target.y)
• the target moves strictly along the y-axis (x= 0, z = 0)

Since we are all visually oriented (arenâ€™t we?), I would wrap your description up as follows:

One thing strikes me though:
you donâ€™t specify what you expect for distances below 10 [units] and above 30 [units] from the target. I sketched two possible outcomes above, visualized as dashed lines. Please specify.

So, what this boils down to, from my point of view is:

the distance â€śdâ€ť between camera and target can be computed as

`d = Math.sqrt( camera.x * camera.x + camera.z * camera.z)`

And you want to do a LERP of the target.y (and camera.y) , based on the cameraâ€™s distance from the y-axis, between the values 10 and 15.

I propose the following:

`target.y = camera.y = 10 - ( d - 20 ) / (20 - 10 ) * (15 - 10)`

Thanks for answer. I ask this question over 10 months and I still not full solved.
I did a workaround time ago on my tick() function trying to solved it; works but is not the desired result.

``````if (this.camera.position.distanceTo(this.controls.target)<=20)
{
this.camera.position.y=15;// prevents vertical rotation
this.controls.update();
}
else
{
this.controls.target.y=10; //torso bone
this.controls.update();
}
``````

If you see the video above. When I zooming in and th distance between camera & orbitControls target is below 20 it jumps aggressively instead of gradually being increased (as you showed in your graphic).

About what I expect for distances below 10 UNITS and above 30 UNITS. Nothing I put limits. So user canÂ´t zoom out above 30 UNITS and canÂ´t Zoom in below 10 UNITS.

I will test your code ASAP. Thanks for your help. I really appreciated

Coming back to your problem: Iâ€™ve looked at the video and it matches your code snippet. It may not be what you wanted, but it is exactly what you coded. Hereâ€™s why:

The blue line shows your intended behaviour, the red line shows your implemented behaviour.

Actually you want a continuous transition from the lower-right state (d â‰Ą 20, y = 10) to the upper-left state (d = 10, y = 15). Itâ€™s crucial to understand, that the transition zone comprises both a distance interval and a height interval.

You implemented a mere threshold, an instant switch from y.start to y.end without spreading the height change over the allowed distance interval.

As you enter the transition zone, coming from the lower-right side and following along the blue arrow, youâ€™ll want to increase the y-value at the same rate as youâ€™re consuming the distance zone.

``````  0% distance covered =>   0% height added
100% distance covered => 100% height added

n% distance covered =>   n% height added
``````

You canâ€™t do that using an `if .. else` construct. You need to compute the fraction of the distance zone consumed, then add that same fraction of the height zone to the initial height. The following should do the trick:

``````let dStart = 20;
let dEnd = 10;
let yStart = 10;
let yEnd = 15;
let deltaWidth = dStart - dEnd;
let deltaHeight = yEnd - yStart;
let d, y fract;
...
d = this.camera.position.distanceTo(this.controls.target)
fract = ( dStart - d ) / deltaWidth;

y = fract > 0 ? yStart + fract * deltaHeight : yStart;  // LERP only inside transition zone

this.controls.target.y = y; // head bone position
this.camera.position.y = y; // prevents vertical rotation
this.controls.update();

``````
1 Like

Thank you very much. Your solution gave me exactly the result I was looking for. You are very good at math.

1 Like

Thanks for your praise, but I would like to deflect that a little bit:
I think Iâ€™m good at explaining things, while the math involved was actually pretty insignificant.

Please post a new video showing the result.

In fact that is true too. You know how to explain very well.

What I like about your code is that it blends very well with the code I have and it doesnâ€™t affect the times when I â€śstressâ€ť the camera.

Here is the video. And again. Thanks

1 Like