Sign in to follow this  
Followers 0
AlexB

Smooth Camera Follow

61 posts in this topic

Hey guys, I thought I'd post this for anyone to use. I wrote this function for Away3D, and I just ported it to TypeScript to see if it would work with Babylon. Basically, you run the moveCamera function in your render loop. It takes a FreeCamera and a target mesh and follows the object around using easing. Mostly like the ArcRotate camera but it doesn't have a set distance. It sets a "goal" for (x,y,z) and eases to it. So you can use this to follow a character around or a ball, etc.

 

Anyway, here's the code in TS. If this is useful to anyone I can take the time to create a fork and submit a PR?

module cameras {export class CameraFollow {public radius:number = 12;public CAMERA_SPEED = 0.05;public MAX_CAMERA_SPEED:number = 20;public orbit:number = 0;public height:number=3;constructor() {}private getRadians (degrees):number {return degrees * Math.PI / 180;}public moveCamera(camera:BABYLON.FreeCamera, cameraTarget:BABYLON.AbstractMesh) {if (!cameraTarget)return;if (!camera)return;var radians:number = this.getRadians(cameraTarget.rotation.y - this.orbit);var targetX:number = cameraTarget.position.x + Math.sin(radians) * this.radius;var targetZ:number = cameraTarget.position.z + Math.cos(radians) * this.radius;var dx:number = targetX - camera.position.x;var dy:number = (cameraTarget.position.y + this.height) - camera.position.y;var dz:number = (targetZ) - camera.position.z;var vx:number = dx * this.CAMERA_SPEED * 2;//this is set to .05var vy:number = dy * this.CAMERA_SPEED;var vz:number = dz * this.CAMERA_SPEED * 2;if (vx > this.MAX_CAMERA_SPEED || vx < -this.MAX_CAMERA_SPEED) {vx = vx < 1 ? -this.MAX_CAMERA_SPEED : this.MAX_CAMERA_SPEED; //max speed is 40}if (vy > this.MAX_CAMERA_SPEED || vy < -this.MAX_CAMERA_SPEED) {vy = vy < 1 ? -this.MAX_CAMERA_SPEED : this.MAX_CAMERA_SPEED;}if (vz > this.MAX_CAMERA_SPEED || vz < -this.MAX_CAMERA_SPEED) {vz = vz < 1 ? -this.MAX_CAMERA_SPEED : this.MAX_CAMERA_SPEED;}camera.position = new BABYLON.Vector3(camera.position.x + vx, camera.position.y + vy, camera.position.z + vz);camera.setTarget(cameraTarget.position);}}}

Share this post


Link to post
Share on other sites

I added this. 

 

https://github.com/jumpkick-studios/Babylon.js/blob/master/Babylon/Cameras/babylon.followCamera.ts

 

Usage is really simple:

//adjust the paramsscene.activeCamera.heightOffset=4; //height above the objectscene.activeCamera.rotationOffset=180; // follow from the rearscene.activeCamera.radius=12; // how far from the objectscene.activeCamera.cameraAcceleration=0.05 // how fast to movescene.activeCamera.maxCameraSpeed=20 // speed limit//follow the objectengine.runRenderLoop(function() {   scene.render();   var car=scene.getMeshByName("car");   scene.activeCamera.follow(car);});
Dad72 likes this

Share this post


Link to post
Share on other sites
This feature is interesting. I tested it. Currently I use an ArcRotateCamera that follows a character.

 

Is it works with all cameras? (free, rotate...)

 

Thanks for the feature.

Share this post


Link to post
Share on other sites

Right now it's just extending the FreeCamera. I was thinking that the problem with the ArcRotate is that it sets a certain distance from the object and sticks to it, so there's no easing. So if you were making a car game, you wouldn't want to just lock to the car or else your view would be jerky. The first example above used a composition but I was thinking it would be better as its own camera type and extending the basic free camera. I think to use with the ArcRotate you'd have to override some of the positioning anyway so I'm not sure how useful it would be there.

Share this post


Link to post
Share on other sites

The only ask I can make is: keep it simple and remove the follow function. by default the camera._checkInputs function is called on every frame

 

Other question: are you using collisions mecanism from freeCamera? if no, I would prefer creating a brand new camera (but using collisions can be interesting tough:))

Share this post


Link to post
Share on other sites

Hi Deltakosh, let me look at the code a little more closely tomorrow. I'm not using the collisions, I only subclassed the freeCamera because I thought it was the right one to use. I'm happy to adjust, but can you explain the request about the follow function? Should I move the follow invocation into the _checkInputs call? Perhaps it should use the target property you already have? Again, I'll take a look, but any guidance you have would be great!

Share this post


Link to post
Share on other sites

First of all thank you for your submission :)

 

Yes please move the code from follow to _checkInputs so that user should not have to call it :) (I always try to reduce the number of line of code that the user must have to use)

 

Also using the target property could be better :)

Share this post


Link to post
Share on other sites

Great, and you're welcome. This library is just phenomenal! So I should have an update soon. I took out the follow command and made the camera subclass BABYLON.Camera, removing superfluous code. Now it won't check inputs anymore at all, which really it shouldn't. If it's just trying to follow a car, then you use inputs to move the car, not the camera, right?

 

I also added a "target" property so the user can use it like this:

camera.target=myCharacter;

Then the camera just locks onto that mesh's position and rotation from that point on. I just need to do some more testing and clean up the code. One question, though:

 

I copied a lot of the code from the freeCamera class, so now the code isn't as DRY as it should be. Should there be some sort of other class we create that extends Camera, that both freeCamera and followCamera could extend?

Share this post


Link to post
Share on other sites

I think that works, although I'm not sure it's very descriptive. Would you like me to integrate this?

Share this post


Link to post
Share on other sites

As you wish :) This is your idea so feel free to integrate it

 

But if we can keep the inheritance from freeCamera it would be even simpler. You should just have to deal with collisions right?

Share this post


Link to post
Share on other sites

I wasn't planning on dealing with collisions at all. Actually, I'm not so sure how to accomplish this. So maybe I take it as far as I can and if someone wants to work with collisions they can use my version as a base?

 

Either way, I can do the DRY stuff and then I'll submit a new PR.

Share this post


Link to post
Share on other sites

Ok, I think I have it working, but I'm running into issues testing. I'm using PHPStorm (not Visual Studio) and if I add the two new camera files manually it works, but if I build the code using Gulp, I get some strange errors. I'm totally lost in VS2013 (installing now) but I may need some help integrating. Stay tuned.

Share this post


Link to post
Share on other sites
You have some explanation and example on FollowCamera and TargetCamera. What are their differences?

 

Support it the Anaglyph as the freeCamera or the ArcRotateCamera? consider it you? This would be very useful.

 

Thanks for these new camera.

Share this post


Link to post
Share on other sites

targetCamera is really just a base class to avoid writing code twice. 

 

freeCamera usage has not changed.

 

followCamera works like this.

 

 var camera = new BABYLON.FollowCamera("FollowCamera", new BABYLON.Vector3(0,0,0), scene);        camera.heightOffset = 8; //how high up from the object to place the camera        camera.radius = 30; // how far from the object to follow        camera.rotationOffset = 180; //rotate around the object (if it's imported strangely or you want to follow from the front)        camera.target = myMeshObject; //any mesh or object with a "position" Vector3        scene.activeCamera = camera; //set the active camera
Dad72 likes this

Share this post


Link to post
Share on other sites

It's doing exactly what it should. The rotationOffset is the angle at which it should orient itself as the "goal" rotation. So try adding some keyboard controls to move your model. Make a left/right key turn your model and change its direction. The camera should swing smoothly around and continue following, still from the back. It's the easing that helps this work nicely.

 

ETA: Maybe there's a bug here. Doing some testing...

Share this post


Link to post
Share on other sites

I fixed the bug and submitted a pull request. I didn't realize that Babylon rotations were already in radians, so my conversion formula was not correctly following the mesh.

 

To fix, change this line:

var radians = this.getRadians(cameraTarget.rotation.y - this.rotationOffset);

To:

var radians = this.getRadians(this.rotationOffset)+cameraTarget.rotation.y;

Now, if you rotate your model, the camera should follow correctly.

Share this post


Link to post
Share on other sites

Hey Alex... thanks for the new camera!  (And thanks for showing us how to use it, too!)

 

Umm... I have some concerns.  I'm not much of a coder, but, 'easing' seems like it COULD be complicated.  There's linear, and log, and ease-in and ease-out, etc.  There could be lots of properties to give the user flexibility in 'easing types'. 

 

Is there potential for CPU slowdown while easings are finishing?  Are the easings on forked threads?  ;)  (Just being funny.  I don't think we have forking in JS.)

 

FollowCam is a great tool/idea, and I'd love to see it code-tight and feature-fleshed (whatever the hell THAT means).  :)

 

Now I'll ask something seriously uninformed.  Can it be done without creating a new class called TargetCamera?  Maybe it CAN be done that way, but it shouldn't?

 

Again, pardon my lack of programming experience, especially when it comes to inheritence.  All you JS Gods probably have all these things totally under control.  I'm just trying to figure out if TargetCamera should be included in our cameras tutorial, or if it is a special tool used (only) for FollowCamera (and thus maybe NOT included in our tutorials).  *shrug* 

 

FollowCamera is DEFINITELY going into our camera tutorial.  It rocks!  (Well, it probably only rocks when its target is a physics-active box that is bouncing around on a rubber-room floor.)  :) I bet THAT would wear-out the gimbal bearings on the FollowCamera rather quickly.

Share this post


Link to post
Share on other sites

Hey Alex... thanks for the new camera!  (And thanks for showing us how to use it, too!)

 

Umm... I have some concerns.  I'm not much of a coder, but, 'easing' seems like it COULD be complicated.  There's linear, and log, and ease-in and ease-out, etc.  Is there potential for CPU slowdown while easings are finishing?  Are the easings on forked threads?  ;)  (Just being funny.  I don't think we have forking in JS.)

 

FollowCam is a great tool/idea, and I'd love to see it code-tight and feature-fleshed (whatever the hell THAT means).  :)

 

Now I'll ask something seriously uninformed.  Can it be done without creating a new class called TargetCamera?  Maybe it CAN be done that way, but it shouldn't?

 

Again, pardon my lack of programming experience, especially when it comes to inheritence.  All you JS Gods probably have all these things totally under control.  I'm just trying to figure out if TargetCamera should be included in our cameras tutorial, or if its a special tool used (only) for FollowCamera.  *shrug*  I included many other dumb comments just because I was curious.  :)

 

Hi Wingnut, I'm 100% sure the code can be tightened up. I've been really busy and honestly rushed it out a bit. But to answer your questions:

 

Easing can definitely slow things down. I'm doing some basic trig functions to calculate the x and z position of the camera, based on the angle of the object. If you know the angle/hypotenuse of a triangle, then the opposite and adjacent are easy to figure. The only thing I can think of to optimize this is to only do these calculations where the "goal" position is within a threshold of the actual position. Maybe store the previous vector and compare before doing further calculations? I just don't know if this will make it better or worse :-)

 

So, why create the subclass? I'm using a lot of the code from the freeCamera, and Deltakosh correctly noticed that a lot of that code wasn't being used, which is a bad idea. So I guess we can do two things. a) we can write a new class that duplicates some code from freeCamera (bad idea since then we have the same code in two places, which means any bug fix happens twice or creates new bugs) or we make a subclass. I'm sure there are other approaches too, but I'm not comfortable enough with the code base to get too radical :-) Always open to suggestions!

 

Also, I *think* TargetCamera should not be included in a tutorial, since it really is just a common library of code for both freeCamera and followCamera. I take it you don't have an entry on the basic camera?

Share this post


Link to post
Share on other sites

Wow, thanks Alex... good information.  Correct, the basic camera isn't mentioned in the cameras tutorial.  I won't plan on adding TargetCamera to the tutorial, but I am not the only tutorial editor or decision maker regarding such things. 

 

And you are certainly welcome to add things to the cameras tutorial yourself, too, at any time.  Also, just because the FollowCamera goes into the tutorial, does not mean you/we can't add features and make changes, so please don't feel handcuffed or rushed by anything.

 

It's very kind of you to be open to suggestions, and thanks again for ALL your good coding work and information... well done.

 

I don't know if you follow the Tutorial Talk thread, but we have been learning about the FollowCam with the help of some playground scenes... starting around here in the thread.  Most of MY talking there... happened before I discovered THIS thread... which answers many of my questions.  I should learn to read more... before talking, eh?  :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Recently Browsing   0 members

    No registered users viewing this page.