zoomOnMeshesHierarchy inconsistent camera rotation

When using zoomOnMeshesHierarchy (or zoomOnMeshHierarchy) the final rotation of the camera is dependent on the value of framingTime.

But IMO it seems the final result once the framing is finished should be the same regardless of how long the animation takes… I.E. shouldn’t framingTime just control how long it takes to animate to that result, rather than altering the final result?

For example here is a simple PG using the default framingTime of 1500 ms and here is the same PG using 0 for framingTime, which results in the camera having an alpha value about 180 degrees greater, leading to a very different result visually…

Using values for framingTime that are in between 0 and 1500 cause the camera’s rotation to end up in between the two above results, making the final rotation of the camera seem like a side effect of the length of the animation, when IMO it seems like varying framingTime should only vary how long the animation takes to reach the same final rotation value, which seems to be how zoomOnMesh already behaves currently…

Also there’s a small variation in beta as well, but the difference in alpha is much more dramatic. I tried setting elevationReturnTime to -1 or to the same value as framingTime, but neither seemed to help (although I’m not sure if that setting is applicable here since it’s not needed to produce consistent results using zoomOnMesh). :slight_smile:

When an animation has a duration (in this case, framingTime) of zero, it will just set the animated property to equal the end value (eg. camera.target = zoomTarget). The reason I’m bringing this up is because I know that when you change an ArcRotateCamera’s target, it will call setTarget which, in turn, will call rebuildAnglesandRadius(). I think that this is what’s causing such a difference between initial alpha/beta values and final alpha/beta values. With a longer framingTime, I’d imagine that the changes would be tiny, as compared to an instantaneous change (framingTime == 0). I suspect that this is the reason why you’re seeing what you’re seeing. I’ll take a deeper look to verify it and I think I know how to fix it.

2 Likes

Awesome, thanks for looking into it! Also I double checked and zoomOnMesh actually does have this behavior too (I thought not but it’s easier to see it with a box mesh). :slight_smile:

Hey @Blake, after digging into the code and asking around here’s what I’ve found. In general, there will be some deviations in the alpha and beta values due to adjusting for default lower and upper alpha and beta limits. Additionally, there appears to be some adjustment for bounding info.

For the framingTime = 0 (and for any setTarget or "target = " lines), since FramingBehvaior calls setTarget via its Animation.TransitionTo call, we are unable to set the cloneAlphaBetaRadius param to true.

// Function Signature
public setTarget(target: AbstractMesh | Vector3, toBoundingCenter = false, allowSamePosition = false, cloneAlphaBetaRadius = false): void

Because of this, rebuildAnglesandRadius will run and change the alpha. Because of some protections against divide-by-zero scenarios, the default end value for the alpha angle after rebuildAnglesandRadius will be PI / 2. Since we’re going into it with an alpha of 0, this would explain the 45 degree rotation. Based on my information, I would believe that this is not a bug but unfortunately, it’s by design.

With all that being said, I did come up with an idea for how to make the camera move without changing the angle. Basically, we’d just have to add an option to tell the camera to treat that cloneAlphaBetaRadius param as being true. We could always just add an override bool to the ArcRotateCamera (eg. overrideCloneAlphaBetaRadius or something like that) to give us the option to change that behavior for all setTarget calls. What do you think?

Awesome, thanks again - I tried it out locally and so far it’s working perfectly to make the result consistent, independent of the framingTime! :smile: It looks like adding that boolean property to the ArcRotateCamera would be a straight-forward approach to implement and easy to use too I think… I can test it some more this weekend and make a little PR for it. :slight_smile: :beers:

So here’s a little PR for it, disabled by default to prevent a breaking change. LOL it turned out to be only 2 lines of new code, but worked like a charm to allow framingTime to be changed independently.

I just made it a draft PR for now thou, in case you had something else in mind. :slight_smile:

2 Likes

Hey @Blake, it looks good to me. I approved it.