Fixing ChaseCamera

I’m not sure I follow what you’re saying here. The only limit you have is when you want to rotate below the spatial’s z axis farther than -90 degrees (looking straight up) and limited to 90 degrees (looking straight down). You can rotate the camera around the spatial (left/right) without limit.



As far as changing the up vector of the chase cam, I’m not so sure it would be a good thing. My opinion is it would be very confusing.



In the end if you want those features you’ll have to adapt the chase cam’s code to your specification, but chances are it won’t be integrated into the official class as this is a very specific case.



I’m not the one making deicisions, but that’s what I think.

im only suggesting this cuz the code already has a “setUpVector”… it just doesnt work right…



along the lines of unlimited rotation, you would just reset the values when a user does a full circle… but either way, your solution actually works provided the UpVector can be modified…

The problem here, at least to me it is one, is when you rotate farther than 90 or -90 you’ll have either of those:


  • The camera will suddenly twist (similar to what it was previously doing) as it switches up vector.
  • You will have to slerp the camera’s up vector from (for example) Vector.UNIT_Y to -Vector.UNIT_Y and from previous discussions, that’s the kind of “bloat” we feel is unneeded.



    But again, as I said, I’m not the one making the decision. :slight_smile:

yeah, you actually fixed one of 2 issues :P…



i think i found why the “UpVector” is not working properly…

actually… it works properly, since it changes the “UP” in the camera, but:

[java]

public void updateCamera() {

float hDistance = distance * FastMath.sin((FastMath.PI / 2) - vRotation);

Vector3f pos = new Vector3f(hDistance * FastMath.cos(rotation), distance * FastMath.sin(vRotation), hDistance * FastMath.sin(rotation));

pos = pos.add(target.getLocalTranslation());

cam.setLocation(pos);

cam.lookAt(target.getLocalTranslation(), initialUpVec);

}

[/java]



updateCamera always assumes Y to be the “UP” in the equations… and, at least to my understanding, is why when using setUpVector the camera gets wonky and rotates all over the place…



this should probably be a new post instead of lurking inside yours, sorry about that, but i though about asking before meddling… i really never messed with the JME3 code so im not entirely sure about the rules (reading the handbook though, commiting rules and other stuff as well…)

Posting in this thread is fine. Don’t worry.



As for the code you posted… Where is this coming from? What I have here in ChaseCam.java doesn’t look like this at all.

i was quite lazy to make the project in eclipse and search within it, so instead i googled it xD



http://code.google.com/p/jmonkeyengine/source/browse/branches/jme3/src/core/com/jme3/input/ChaseCamera.java?r=5837



this might be an old revision? (says Sep 18, 2010)

edit: yeah, it was an old revision :blush: me bad xD



edit2:

[java]

protected void computePosition() {



float hDistance = (distance) * FastMath.sin((FastMath.PI / 2) - vRotation);

pos.set(hDistance * FastMath.cos(rotation), (distance) * FastMath.sin(vRotation), hDistance * FastMath.sin(rotation));

pos.addLocal(target.getWorldTranslation());

}

[/java]



still, the same code is used, just elsewhere…



the calculation of the position is made assuming that Y is always UP ("(distance) * FastMath.sin(vRotation)")…

X=R*cos(φ)sin(θ) => this is X in the equation above

Y=R
sin(φ)sin(θ) => this is Z

Z=R
cos(θ) => this is Y (although it’s sin instead of cos, could be using the other angle, not sure)





that, combined with this:

[java]

public void setUpVector(Vector3f up){

initialUpVec=up;

}

[/java]

makes a coctel of wonky rotations if you change the UpVector…



edit3: i wish i had a mathematician next to me… i think this could be solved by using non-linear values here:

[java]

public void onAnalog(String name, float value, float tpf) {

if (name.equals(ChaseCamMoveLeft)) {

rotateCamera(-value);

} else if (name.equals(ChaseCamMoveRight)) {

rotateCamera(value);

} else if (name.equals(ChaseCamUp)) {

vRotateCamera(value);

} else if (name.equals(ChaseCamDown)) {

vRotateCamera(-value);

} else if (name.equals(ChaseCamZoomIn)) {

zoomCamera(-value);

if (zoomin == false) {

distanceLerpFactor = 0;

}

zoomin = true;

} else if (name.equals(ChaseCamZoomOut)) {

zoomCamera(+value);

if (zoomin == true) {

distanceLerpFactor = 0;

}

zoomin = false;

}

}

[/java]

im just guessing here, i dont have a working trunk version of JME3 to compile and run tests on… i’ll probably just make a crappy version of chaseCam and try to find a posible solution…

I’ll leave that for @nehon to answer.

ok mate :slight_smile: thx a bunch though…

well… as a quick fix, if you switch around X,Y,Z to fit the UpVector in the computePosition equation, that works… but i actually want all the intermidiate points… like having (1,1,0) as an up vector… this should be achieved by rolling the camera, thus changing the UpVector acordingly… im still trying to figure out how to do this :?



edit: so, 4 hours after this post, after RE-reading all this:

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:intermediate:math

http://public.iwork.com/document/es/?a=p99920633&d=jMonkeyEngine3-Math.key

https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:math

and countless other forum pages: (a couple of the best finds)

Camera problem: rolling

Camera rolling - Graphics and GPU Programming - GameDev.net



and having asked 2 diff mathematician friends, im still wondering how the hell to fix this…

well… i made some progress using quaternions… but there’s still a few places where the camera is acting weird… though i managed to fix all the unit vectors… or so i believe… im still missing something…



edit:

heres the code of what i managed to do so far



[java]

protected void computePosition() {



float hDistance = (distance) * FastMath.sin((FastMath.PI / 2) - (vRotation));

pos.set(hDistance * FastMath.cos(rotation), (distance) * FastMath.sin(vRotation), hDistance * FastMath.sin(rotation));



Quaternion roll= new Quaternion();

roll.fromAngleAxis(initialUpVec.z*(FastMath.PI / 2), Vector3f.UNIT_X);

//roll.lookAt(initialUpVec, Vector3f.UNIT_Y);

pos.set(roll.mult(pos));



roll.fromAngleAxis(initialUpVec.x*(FastMath.PI / 2), Vector3f.UNIT_Z);

pos.set(roll.mult(pos));



//roll.fromAngleAxis((initialUpVec.y-1)(FastMath.PI / 2), Vector3f.UNIT_X);

//pos.set(roll.mult(pos));



pos.addLocal(target.getWorldTranslation());





/


cam.setLocation(new Vector3f(0,0,0));

//cam.lookAt(new Vector3f(rotation,0,vRotation), new Vector3f(0,1,0));

cam.lookAt(pos, initialUpVec);

Vector3f camDir = cam.getDirection().clone().multLocal(1.25f);

pos.set(camDir.negate());

pos.addLocal(target.getWorldTranslation());

*/



}

[/java]



theres some commented stuff that i thought could work, some did, partially, so i kept it…

if someone can improve on this and fix the UpVector for all posible values, i would be forever grateful…



this seems to work fine for (1,0,0),(0,1,0) and (0,0,1)… but (1,0,1) already acts weird…

The problem here IMO is that you are trying to make the chaseCam act in a way it was not designed for.

From experience, it’s easier and faster to re-implement something that suits exactly to your needs instead of bending something that almost meet them.



I said it numerous times, and i should add this as disclaimer in the javadoc : ChaseCam is an example of what can be done with JME in the particular case of a cam following a moving target. It was designed in the idea of a character moving on solid ground and the idea of rotating over 90 degrees above him was not even considered.

I added some features over time as they were asked on this forum that resulted in some bloats as Madjack mentioned.



The reality is that there is no such thing as the “PerfectCamera” that will suits all video game styles. Moreover the way the camera behave in a game is IMHO 50% of the gameplay, and to get to what you like you have to make choices and compromises.



I would only use the ChaseCam if it suits my needs and/or if I could cope with its issues.

Also the code could be simplified a lot by using just using a simple node copying the targets translation with a camera node attached to it. That would skip a lot of math.

Also a mistake i made in the ChaseCam is to lerp between euler angles instead of slerping between quaternions. This can bring some gimbal lock condition that could be the very reason of the twisting you’re mentioning.



My conclusion is : you want a chase cam that rotates all around your target? Make your own control that does this, it will be faster to implement.

ok then… thx…

still… im not trying to add anything new to it, just fix “setUpVector” :slight_smile:



cheers…



edit: i think i just figured out how to do everything with quaternions and take out the sphere equations that are causing so much trrouble…

if you like my solution, it can be used instead, basically fixing the setUpVector :wink:

so this only took like 20 hours or so for me to figure out >.< (dammit jim, im a programmer, not a mathematician)



[java]

protected void computePosition() {



cam.setLocation(new Vector3f(0,0,0));



Vector3f magicVect=new Vector3f(-initialUpVec.y,-initialUpVec.z,initialUpVec.x);

Vector3f magicVect2=new Vector3f(magicVect.cross(initialUpVec));



pos.set(magicVect);



Quaternion roll= new Quaternion();

roll.fromAngleAxis(vRotation, magicVect2);

pos.set(roll.mult(pos));



roll.fromAngleAxis(rotation, initialUpVec);

pos.set(roll.mult(pos));



cam.lookAt(pos, initialUpVec);





Vector3f camDir = cam.getDirection().clone().multLocal((distance) *1.25f);

pos.set(camDir.negate());

pos.addLocal(target.getWorldTranslation());





}

[/java]



this fixes setUpVector, making it posible to set ANY up vector, and if left to the default (0,1,0), still performs as usual…

i know it looks horrible and there might be place to optimize it further, but i just cant deal with the equations anymore :? :cry:



even if it’s not changed or added, it will be nice for it to be on the forums, just in case someone actually wants a chaseCam for a plane or otherwise weird “up” changing moving character…



(looking at it again, im even surprised i could came up with this xD, it actually sounds logic if you look at it a little bit at a time…)



anywayz… enjoy :slight_smile:

(and do let me know if you decide to swap it in the JME3 trunk ;))

1 Like

Thank you.

I’ll integrate and test it.