Fixing ChaseCamera

This is mostly for @nehon



I’m fixing the ChaseCamera so when it’s getting to the max rotations (Min/Max Vertical) it doesn’t “twist” when it gets at those values (up/down rotation). I’m also adding a flag to check if rotation should be tied to minDistance. That’s the plan.



It’s mostly all done but I’ve got some questions / need input.



First, the “twist” when you get to maxVerticalRotation/minVerticalRotation. This is fixed by using the following, but I’m not entirely sure why it was doing this in the first place.

[java]

//rotate the camera around the target on the vertical plane

private void vRotateCamera(float value) {

if (!canRotate || !enabled) {

return;

}

vRotating = true;

float lastGoodRot = targetVRotation;

targetVRotation += value * rotationSpeed;

if (targetVRotation > maxVerticalRotation) {

targetVRotation = lastGoodRot;

}

if ((targetVRotation < minVerticalRotation) && (targetDistance > (minDistance + 1.0f))) {

targetVRotation = lastGoodRot;

}

}

[/java]



The fix involves setting targetVRotation to lastGoodRot. The original way was to set it to maxVerticalRotation/minVertivalRotation respectively. Why it was doing this twisting… is beyond me. All I know is that by using the above, it now works properly. Thoughts?



The second thing is about zoomCamera.



[java]

//move the camera toward or away the target

private void zoomCamera(float value) {

if (!enabled) {

return;

}



zooming = true;

targetDistance += value * zoomSpeed;

if (targetDistance > maxDistance) {

targetDistance = maxDistance;

}

if (targetDistance < minDistance) {

targetDistance = minDistance;

}

if ((targetVRotation < minVerticalRotation) && (targetDistance > (minDistance + 1.0f))) {

targetVRotation = minVerticalRotation;

}

}

[/java]



The question is about the last if. Is this a “copy/paste” oversight? I don’t see a purpose to this. I’ve commented it here and there were nothing showing a difference on the screen. AFAIK, rotation checking doesn’t belong in zooming… But I might be wrong.



minDistance vs rotation flag.

I know I need this for my game, but I’m wondering if it’d be worth it to add a branching. In the grand scheme of things I don’t think it would make any impact but I prefer asking.



Lastly, I will change some var naming/javadoc because some methods are referring to angle when it actually should be radian. I’ve burned my fingers at first. Not a big issue at all, but preferable to have it right so there is less confusion.



Thanks.

2 Likes

One question / feedback I have on chaseCam is would it be possible to implement a way to change the rotation orientation of the target camSpatial that the cam is currently looking at. For example if when attaching a chaseCam to an abject when the camera appears to be facing the side of the object, instead of behind the object.

awchum :smiley: <33

@lwsquad said:
One question / feedback I have on chaseCam is would it be possible to implement a way to change the rotation orientation of the target camSpatial that the cam is currently looking at. For example if when attaching a chaseCam to an abject when the camera appears to be facing the side of the object, instead of behind the object.


Just use: chaseCam.setDefaultHorizontalRotation(-FastMath.DEG_TO_RAD * 90);

Works fine here.

Here’s the diff with the improvements mentioned above. I’ll wait to get a reply to my queries before committing.



[patch]

This patch file was generated by NetBeans IDE

It uses platform neutral UTF-8 encoding and n newlines.

— Base (BASE)

+++ Locally Modified (Based On LOCAL)

@@ -82,6 +82,7 @@

protected boolean zooming = false;

protected boolean trailing = false;

protected boolean chasing = false;

  • protected boolean veryCloseRotation = true;

    protected boolean canRotate;

    protected float offsetDistance = 0.002f;

    protected Vector3f prevPos;

    @@ -297,10 +298,7 @@

    if (targetDistance < minDistance) {

    targetDistance = minDistance;

    }
  •    if ((targetVRotation &lt; minVerticalRotation) &amp;&amp; (targetDistance &gt; (minDistance + 1.0f))) {<br />
    
  •        targetVRotation = minVerticalRotation;<br />
    

}

  • }



    //rotate the camera around the target on the vertical plane

    private void vRotateCamera(float value) {

    @@ -308,14 +306,21 @@

    return;

    }

    vRotating = true;
  •    float lastGoodRot = targetVRotation;<br />
    

targetVRotation += value * rotationSpeed;

if (targetVRotation > maxVerticalRotation) {

  •        targetVRotation = maxVerticalRotation;<br />
    
  •        targetVRotation = lastGoodRot;<br />
    

}

  •    if (veryCloseRotation) {<br />
    

if ((targetVRotation < minVerticalRotation) && (targetDistance > (minDistance + 1.0f))) {

  •        targetVRotation = minVerticalRotation;<br />
    
  •            targetVRotation = lastGoodRot;<br />
    

}

  •    } else {<br />
    
  •        if ((targetVRotation &lt; minVerticalRotation)) {<br />
    
  •            targetVRotation = lastGoodRot;<br />
    

}

  •    }<br />
    
  • }



    /**
  • Updates the camera, should only be called internally

    @@ -576,15 +581,14 @@

    }



    /**
  • * returns the maximal vertical rotation angle of the camera around the target<br />
    
  • * @return<br />
    
  • * @return The maximal vertical rotation angle in radian of the camera around the target<br />
    

*/

public float getMaxVerticalRotation() {

return maxVerticalRotation;

}



/**

  • * sets the maximal vertical rotation angle of the camera around the target default is Pi/2;<br />
    
  • * Sets the maximal vertical rotation angle in radian of the camera around the target. Default is Pi/2;<br />
    
  • @param maxVerticalRotation

    */

    public void setMaxVerticalRotation(float maxVerticalRotation) {

    @@ -592,15 +596,15 @@

    }



    /**
  • * returns the minimal vertical rotation angle of the camera around the target<br />
    
  • * @return<br />
    
  • *<br />
    
  • * @return The minimal vertical rotation angle in radian of the camera around the target<br />
    

*/

public float getMinVerticalRotation() {

return minVerticalRotation;

}



/**

  • * sets the minimal vertical rotation angle of the camera around the target default is 0;<br />
    
  • * Sets the minimal vertical rotation angle in radian of the camera around the target default is 0;<br />
    
  • @param minHeight

    */

    public void setMinVerticalRotation(float minHeight) {

    @@ -608,8 +612,7 @@

    }



    /**
  • * returns true is smmoth motion is enabled for this chase camera<br />
    
  • * @return<br />
    
  • * @return True is smooth motion is enabled for this chase camera<br />
    

*/

public boolean isSmoothMotion() {

return smoothMotion;

@@ -742,21 +745,21 @@

}



/**

  • * sets the default horizontal rotation of the camera at start of the application<br />
    
  • * @param angle<br />
    
  • * sets the default horizontal rotation in radian of the camera at start of the application<br />
    
  • * @param angleInRad<br />
    

*/

  • public void setDefaultHorizontalRotation(float angle) {
  •    rotation = angle;<br />
    
  •    targetRotation = angle;<br />
    
  • public void setDefaultHorizontalRotation(float angleInRad) {
  •    rotation = angleInRad;<br />
    
  •    targetRotation = angleInRad;<br />
    

}



/**

  • * sets the default vertical rotation of the camera at start of the application<br />
    
  • * @param angle<br />
    
  • * sets the default vertical rotation in radian of the camera at start of the application<br />
    
  • * @param angleInRad<br />
    

*/

  • public void setDefaultVerticalRotation(float angle) {
  •    vRotation = angle;<br />
    
  •    targetVRotation = angle;<br />
    
  • public void setDefaultVerticalRotation(float angleInRad) {
  •    vRotation = angleInRad;<br />
    
  •    targetVRotation = angleInRad;<br />
    

}



/

@@ -782,6 +785,21 @@

}



/

  • * @param rotateOnlyWhenClose When this flag is set to false the chase<br />
    
  • * camera will always rotate around its spatial independently of their<br />
    
  • * distance to one another. If set to true, the chase camera will only<br />
    
  • * be allowed to rotated below the &quot;horizon&quot; when the distance is smaller<br />
    
  • * than minDistance + 1.0f.<br />
    
  • */<br />
    
  • public void setDownRotateOnCloseViewOnly(boolean rotateOnlyWhenClose) {
  •    veryCloseRotation = rotateOnlyWhenClose;<br />
    
  • }

    +
  • public boolean getDownRotateOnCloseViewOnly() {
  •    return veryCloseRotation;<br />
    
  • }

    +
  • /**
  • return the current distance from the camera to the target
  • @return

    */

    [/patch]
@madjack said:
Just use: chaseCam.setDefaultHorizontalRotation(-FastMath.DEG_TO_RAD * 90);

Works fine here.



Thanks!

@madjack

@madjack said:

This is mostly for @nehon



The question is about the last if. Is this a “copy/paste” oversight? I don’t see a purpose to this. I’ve commented it here and there were nothing showing a difference on the screen. AFAIK, rotation checking doesn’t belong in zooming… But I might be wrong.



The chase cam turns into a 1st person cam when you are close enough of the target. It allows the cam to rotate below the horizon.
Lets say you completely zoom in,rotate the cam bellow the horizon, then zoom out. Without this if statement the camera will get into the ground.


About your change, it look fine to me, so go ahead and commit.

Thanks for this ;).
@nehon said:
The chase cam turns into a 1st person cam when you are close enough of the target. It allows the cam to rotate below the horizon.
Lets say you completely zoom in,rotate the cam bellow the horizon, then zoom out. Without this if statement the camera will get into the ground.


Ah, I see. Then I'll use the flag there too since we don't want it to snap if we zoom in from underneath.

@nehon said:
Thanks for this ;).

No probs.

I'll commit tomorrow after adding the above and testing.

Turns out I found the problem of the “twisting”, odd behavior…



When you’re allowed to rotate below the “horizon” but your minVerticalRotation is set to 0, as it was by default, there was no check to see where the rotation was at when that occurred.



The only check was:

[java]

if ((targetVRotation < minVerticalRotation) && (targetDistance > (minDistance + 1.0f))) {

targetVRotation = minVerticalRotation;

}

[/java]



which didn’t qualify for that scenario. So you ended up with a twisting effect or in certain cases you could even rotate 360 degrees. To stop that from happening I’m hard-coding a limit of -FastMath.DEG_TO_RAD * 90 which is viewing from underneath the spatial.



So the question now becomes: how do we want to handle that? Keep the hard-coded of -90 degrees or should we have a settable variable for that?



EDIT: I think we should keep the hard-coded limit. There’s no point in adding more to that class, besides I don’t see the point of allowing more than -90 degrees rotation. Less? That could be debated.

Since @normen is browsing around, do you have an opinion on that? :slight_smile:

@madjack said:
Since @normen is browsing around, do you have an opinion on that? :)

nope ^^

Party pooper. :stuck_out_tongue:

:frowning: was just an honest answer, I feel to have an opinion I’d have to have a use case, experience with it etc. etc… :wink:

Bah. I’ll wait for real input then. :wink:



Seriously though, I don’t think we should try to cover each and every possible situation. Doing so would only bloat the class. I’ll still wait for @nehon’s input.

@madjack said:
Seriously though, I don’t think we should try to cover each and every possible situation. Doing so would only bloat the class

Amen to that, the class is already quite bloated really.
We really can't make it fit every single need one would have for a chase cam.

But, your change looks more like fix than a new feature, no one would want the view to flip when reaching the rotation limit, so i think it's safe to commit it.

go ahead!!

The thing is, it’s not about flipping when the rotation limit has been reached. It’s like this:



Pre-req.: Rotation below spatial’s “horizon” disabled except when fully zoomed-in (the default behavior).



If you rotate downward when zoomed-in, I default (hard-coded) the min rotation to -90 degrees (from beneath the spatial tied to chase cam).



Now, what if someone wanted to rotate at a maximum of only up to -45 degrees? Since it’s hard-coded the class itself would have to be modified to accommodate for that. Fixing it properly means adding a variable, a setter and a getter.



That’s what I’m questioning.

Alright, since I’m being ignored :stuck_out_tongue: I’ve decided to commit it as it is.



Regarding the point in the last post above:

Some people might argue that you can’t look down or up while standing up and unmoving while in 1st person view. That it doesn’t look natural. You would be right. The way it is now is physically impossible under current human evolution. So, the only way to fix this is to modify your model animation (if you’re using a bipedal), if you’re using something else then shrug you’ll have to find another justification and solution. :stuck_out_tongue:



So the answer is simple. To look up you would have to rotate the head backwards a bit and to look completely down, move the head forward and down a bit. There! Justification AND solution in one go. :wink:



If that answer doesn’t satisfy you then complain to @nehon as he’s the one who let me play with his little toy. Oh and you can also blame @normen for not having an opinion when I asked for one. :stuck_out_tongue:



Committing in a bit.

Committed.



If there are issues post it here.

2 Likes

erf sorry didn’t saw your previous posts.

That’s fine, thanks for committing :wink:

sorry to dig up this post, but i’ve been having this issue you mention with chaseCam, along with the fact that SetUpVector doesnt do much but mess up the rotation… i was about to make my own chaseCam when i though it would be nicer to just fix this one so others can make better use of it…

i’m digging thru the code in JME3, though since i never modded JME3 it might take me a while…



my goal is to make a chaseCam that can rotate infinite times in any direction, unless restrained to certain bounds, and to be able to change the UpVector, or in other words, to pitch the view to acomodate to a new “up”… (space sim much? :slight_smile: )



if someone already did this and is not yet on JME, is in JME already but on a nightly version, or plans to, please let me know so i stop meddling with JME3 inner workings xD :stuck_out_tongue:



cheers…