Rodrix3

Animate camera programatically

Recommended Posts

We are looking forward to animate the camera, to do some animations where the camera points to different objects and moves by itself.

We are migrating from ThreeJs. We need to set:

  • camera look at (vector3 where the camera is looking)
  • camera position (vector3 where the camera is positioned)

Being able to modify just that, we would be all set. We want to no user interface (camera moves by itself).

What type of camera object (there are so many camera objects in Babylon!) should we create and how can we modify those two properties?
We would be having the code on the render loop.

Thanks so much in advance!

P.S: Animations would be dynamic, meaning we will never have the same animation twice, so I need to be able to do this programatically.

 

Share this post


Link to post
Share on other sites

Hiya Rodrix3.  We recently created THIS playground:  https://www.babylonjs-playground.com/#3U658N#13

It's a panel of HTML buttons that control dynamic ArcRotate camera animations.  It COULD use BabylonJS GUI buttons, too - better for VR head gear.

Although these are "set" animate-to locations, they don't need to be.

Notice that each of the "mover functions" (lines 174-201)... moves TWO things... the camera.position and the camera.target vec3.  Both are needed... to have full animation control of an ArcRotate camera.

Lines 159-169 contain two helper functions... for moving the camera and the target.  It is easy to feed those two functions... with dynamic values (such as selectedMesh.position for the camera.target, and selectedMesh.position.add(wantedVector3CameraOffsetFromTarget) for the camera.position.

Essentially, those two functions (animateCameraTargetToPosition & animateCameraToPosition) give you full orientation control for an ArcCam, right?  AND, the camera works just fine AFTER the animation completes... mouse-drags, control-mouse-drags, mousewheel, keypresses, etc.

These animation functions are BABYLON.Animation.CreateAndStartAnimation, which is the very simplest form of animation-starting.  There are MANY more advanced animation features available.  The animations in the above playground... started here... https://www.babylonjs-playground.com/#HH1U5#72 ... as some simple animation wrapper funcs overloaded onto Babylon.Mesh-class (in lines 2-50).  Makes them handy to call.  You may find these useful, too.  You COULD overload a camera with these animation utility funs... in the very same way.   *shrug*

Anyway, I thought I would share this stuff... get you rolling.  Hope it helps.  Welcome to BabylonJS.  Stay tuned for more comments and more playground examples.

Share this post


Link to post
Share on other sites

@Wingnut thanks so much for your link and in depth explanation.

From ThreeJs I already have a class that controls the easing and modifies the position vector and lookAt vector.

I see that in your sample code the easing is being controlled by Babylon.

I would need to access the render loop and have my class function run there and just modify directly the position and target vectors.

How should I do that?

afterRender, beforeRender? Could you please provide me a super basic example where on each render frame the camera.position.x +=1?

Thanks so much in advance!

Share this post


Link to post
Share on other sites

Hi R.  I'm no expert on these things... but... perhaps one of the newer, fancier ways... is with an observer:

https://www.babylonjs-playground.com/#15FH5P#0

http://doc.babylonjs.com/playground/?code=observer ]

"deltaTime" might be an interesting PG search:  http://doc.babylonjs.com/playground/?code=deltaTime

"requestAnimationFrame" might be a fun search:  http://doc.babylonjs.com/playground/?code=requestAnimationFrame

These are some animation-related terms I see, sometimes, when looking at playgrounds.

Are they useful to my buddy Rodrix?  I doubt it.  :D  But I hope so.

Generally, yeah, if you are step-animating from an array of pre-eased positions or something...  sure... scene.beforeRender = function(){ updateMyAnimations() };  But still, you'll look cooler if you use the observer.  ;)  Perhaps use a freeCam... even IT has a .target and perhaps .lockedTarget... or keep doing camera.setTarget(whatever) continuously, in the [before]renderLoop, or within your constantly-running updater func.

I don't think we have a camera.lookAt().  Only mesh can do that... but if your cam is parented to a mesh (freeCam or universalCam, likely)... then yeah, use the mesh.lookAt... um... repeatedly, I suppose.  I don't think we have a mesh.lockedLookAt()  :)  Could invent one, I suppose.  Yay, trailblazing!  heh

Don't waste much time in your updateMyAnimations().  You know.  You're a pro animator... I can tell.  Activate new anims, wrap-up finished anims, step the in-progress anims, and jump ship.  :)

Most browsers have an object inspector... built-in.  Usually, you can code console.log(camera) and "object" is printed at console window.  Then just click it.  The object inspector should launch, and that is a great way to tour-around, finding cool "knob" names... to twist.  I really like doing "discovery" in the browser's object inspector.  It also helps me memorize available property and method names... on the more-common BJS objects/classes.

The camera class's API works, too.  

I wish the classDocs TOC weren't light-blue on white, and thin-fonted.  No contrast... makes the table a bit difficult to read or something.  Control-mousewheel doesn't improve it much, either.  Where's the theme selector?  :)  (what a whiner, eh?)

Note:  Our classDocs format is brand new... just installed... future tweaks likely.  Massive work - nicely done, so far.  (Wingy hugs the docs team.)

Share this post


Link to post
Share on other sites

Looks good, R!  Well done. 

Using BJS Animation System is probably still "best practice"... but renderLoop animation is considered "common practice" for non-complex animations.

Renderloop animations are sometimes difficult to limit (to stop them at a certain point).

https://www.babylonjs-playground.com/#L7MF8M#3

There is a slight mod to your playground.  First, I turned your camera to face +z with the -Math.PI/2 in camera alpha setting at line 5.  It's a personal preference for me, and is helpful in learning 'scene orientation'.)  Now, -x is left, +x is right, -z is toward cam, +z is away from cam.

So, I also changed the values in lines 26/27... to negative values.  We're now backing the camera away from the mesh... along the negative Z axis.  I turned-off the camera.target animation, allowing the target to remain at its starting point between the two boxes.  No big deal... re-activate at will.

Lines 33/34 puts a simple 'conditional' inside the render loop.  A limiter/stopper.

Also keep in mind... that instead of animating arcCam position and target, you could INSTEAD animate the ArcCam "big three" properties... .alpha, .beta, and .radius.  You could animate camera.fov, too.  (field of view).   Below is a playground... where I removed all conditionals from the renderLoop, then put two conditionals in the animate() function... and then animated the camera.radius to 'dolly-out' the camera, while at the same time increasing camera.beta from current setting... to PI/2 (about 1.57).  With camera.beta, the value range is generally from 0 (looking straight down)... to 3.14 (looking straight up).  So... Math.PI/2 is 1.57 and that means camera is level... with no 'pitch' or with "level pitch".

https://www.babylonjs-playground.com/#L7MF8M#4

 

The ArcRotate cam provides lots of opportunity for animating its "knobs", eh?  :)

And... you can use the "down'n'dirty" renderLoop animation method, or the elegant BabylonJS Animation system... which provides 11 different kinds of ease-ins/outs, and animationEvent generating, and animation blending, and start/pause, etc.

Neither/either method is really 'best practice"... but both ways have their time and place, eh?

Let's re-visit https://www.babylonjs-playground.com/#3U658N#13

See the "CreateAndStartAnimation" in lines 162 and 168?  These are the simplest of the BJS Animation System commands... and I like using them because of a cool feature they have.  Automatic value-type sensing.  Other BJS Animation methods need programmer to set what dataType the animation will be.  Sometimes a float value, sometimes a vector3, sometimes a Quaternion, sometimes a color4, etc.  But the cool CreateAndStartAnimation() call... auto-senses the dataType.  I LOVE that feature!  No need to set it manually.

Here is a playground with pile of BJS Animation/Animatable experimenting... if you need a brain tumor.  https://www.babylonjs-playground.com/#HH1U5#59

I started an investigation into BJS Animations... here:  http://www.html5gamedevs.com/topic/2571-the-wingnut-chronicles/?do=findComment&comment=88290

I 'assembled' a possibly-now-outdated 'central doc' about Animations, once.  It is here:  http://urbanproductions.com/wingy/babylon/misc/wingsBJSanimDoc.html

So much "stuff", eh?  :)

This is all just MY opinion... not necessarily wise or informed.   :)  Comment back, of course, but let's stay tuned to hear what others think, too.  Party on!

Share this post


Link to post
Share on other sites

Thanks so much for the comprehensive answer again!

However, using my method, is there any way to update the camera position by a value related to the frame rate so I can assure that whatever the frame rate is the camera position is updated homogenously through time?

 

In other words, I need my animation to run independent of frame rate.

 

In ThreeJs I used to do this:

var clock = new THREE.Clock();
var speed = 2; //units a second
var delta = 0;

render();
function render(){
  requestAnimationFrame(render);

  delta = clock.getDelta();
  object.position.z += speed * delta;

  renderer.render(scene, camera);
}

 

What is the equivalent in Babylon? As you can see I don't need any fancy coding with easing and such in this particular case (although your solutions might become veryyy handy for other future uses). Right now, I have a complete animation library already coded and I need to use it with Babylon. I just need to connect in the same way... Is it possible? I think I am close but not there yet...

 

Thanks so much!

Share this post


Link to post
Share on other sites

Hi R!  You certainly are kind and cordial.  Thanks for being that way!

Okay, here's some limp Wingnut attempts at finding some info to help...

http://doc.babylonjs.com/playground/?code=getDelta

Apparently, some BJS folks have been making clock objects.  Might be useful.

The Engine class has a .getDeltaTime() that looks interesting, and has 70 playgrounds of usage.

RequestAnimationFrame has a few playgrounds, too.  http://doc.babylonjs.com/playground/?code=requestAnimationFrame

That appears to be a Window thing.  I think I heard that it is not really needed within BJS.  Not sure why.  A forum search might tell why.

I don't know how to use ANY of this animation-stepping stuff, but I bet YOU do, Rodrix.  :)  I hope I've been helpful.  Party on! 

btw... if you ever wish to share your animation library, I'm sure I and others would be glad to store copies on our hard drives... for potential future molesting.  :)

Share this post


Link to post
Share on other sites

@Wingnut, no thanks to you, really. I think I've found a very nice 3d js engine, and in addition a very nice community where I see I will be making some new  friends ;)

 

You asked about my animation library. Yes, I would love to share it!
However, it is not "mine" but  of a developer called spite who contributes on ThreeJs.
He made some great libraries, and this one is engine agnostic. It can be used for any 3d engine, to animate anything!

https://github.com/spite/Storyline.js

I highly recommend it.  Have a look ;)

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


  • Recently Browsing   0 members

    No registered users viewing this page.