Jump to content

How to make FreeCamera push objects


Recommended Posts

Hi everyone!

I am trying to implement a simple thing. I want the player (FreeCamera) be able to push other objects on scene when he collides with it.

The approach I found before is creating of the box and attaching camera to it.

Like this:

camera.parent = playerBox;

and then attach Impostors to playerBox and other pushable objects.

But I completely don't like this.

1) Camera falls if playerBox falls after collision. I want the player to be stable while colliding.

2) I need to reimplement controls for playerBox, including mouse look. Well, it's easy to make playerBox move along axis (X,Y,Z). But what about diagonal movement? What about mouse look? I need to reimplement everything that FreeCamera already can do.


To be honest, I just want FreeCamera to have some mass while it collides. 

Is there an easy way to do this?

Link to comment
Share on other sites

Hiya splash27, welcome to the forum.

     I'm no pro at these things... but I might have found a solution.


Sorry for messy playground.  Test by using up-arrow to drive camera into barrel2, which is straight ahead.  When camera hits barrel2, barrel2 will move away from camera (a small and adjustable amount).  It could use BJS animation or other linear interpolation (lerp)... to move "smoothly" with ease-to-stop, too, perhaps. That would probably work best IF you want a further-distance mesh-move.

Interesting places:

line 68 ... I set a rather fat-belly .ellipsoid on the camera.  :)
lines 177-187 ... a mesh backAwayFromCamera function that... does what it says :)
lines 189-197 ... a camera onCollide func, which calls backAwayFromCamera(meshThatCameraHit)

I did a little sneaky and dangerous thing.  Sometimes, users have a difficult time knowing when a vector3 is a position, and knowing when a vector3 is a direction.  Line 186... uses a direction as a position.  But, what the heck.  The direction [which could be direction.nomalize() as wanted] was a nice little vector3, and I needed a nice little vector3 amount of movement, so I used a direction as an added position.  Not normally a wise thing to do.  :)

The subtraction that happens in line 181... is a direction, as its name implies.  The size of direction's values is somewhat determined by the distance between the camera center and collidedMesh center WHEN COLLISION HAPPENS.  So, direction values vary, depending upon fatness of camera.ellipsoid and mesh.ellipsoid/mesh-size.  Lines 178 and 184 use the mult variable as a "how-much-to-move-mesh" sensitivity setting... which you may need to tweak.

It all seems to work pretty well.  Barrel2 has an actionManager on it, but you can ignore that  (such things would require camera be parented to a mesh, and we both know that sucks). 

Unfortunately, there are no camera-based triggers for actionManagers, and no camera-based observables.  What were they thinking?  :)

Hope this helps.  At least it might give you some more toys to play-with.  Holler back, as wanted.

Link to comment
Share on other sites

My pleasure... hi again.

Umm... no... the physics engines need a mesh/gizmo to assign their impostors-to.  And then... yep... gotta use applyImpulse or setLinearVelocity funcs to move the (invisible) camera parent.

And, friction between camGiz and ground... determine "inertia" of camera (skid-on after thrust shut-off).  Braking can also be used... force-setting linearVelocity quickly to 0,0,0.

And, the camGiz might need fixedRotation (available) to avoid turning upon impact... but that might fight-with using setAngularVelocity needed to turn player or look-around.  But keep in mind that camera can be turned and tilted even when it has a parent.  Orienting the parent is not a requirement... to orient camera.  But, it might be wise to "snap" camera back to forward and level view, when player mesh starts moving... just for user sanity.  :)

Few have tried it.  Perhaps build a playground with a single physics-active box on a grid/textured ground (textured ground so we can "sense" how fast/slow we can set camgizmo linearVelocity to GO and STOP with some keypresses).   Interesting issue.  If you make a nice "physics player controller"... you'd be a local hero.

I don't have a handy playground for ya, but perhaps others can help with that, and will have better ideas, or differing opinions.  Stay tuned.

Link to comment
Share on other sites

So, I started to implement pushing camera. 

Seems like setLinearVelocity might really work. CannonJS physics already has dissipation. So the mesh will stop after it will pass some distance (depends on velocity given).

Another trick is that we could set player's impulse as constant that we will be comfortable with. It's possible, because player's mass and velocity is constant in most cases.

Now it's a really hard thing. I don't know how to get player movement direction. Important to remember that player can collide with meshes when he doesn't even look at. He might look to the sky or go left, right, back before the collision.

I prepared playground with comments. 


It's not done yet. The movementDirectionVector is needed to be calculated.

Link to comment
Share on other sites

Aahh, you decided NOT to use a gizmo-mesh/impostor on the camera itself.  Interesting.  Very creative! 

I was assuming that you would, and MOST of my previous post was talking about how to move/stop the camera gizmo.

An impostor on the camera would give your impacts... direction angles and restitution power... that the physics engine calculated.

But, as we know... camera nav would be more of a challenge, if the camera parent/gizmo had physics.

Anyway, direction.  If you do... var dir = camera.position.subtract(collidedMesh.getAbsolutePosition())... you will get a direction... which might need a .negate() to turn it the correct direction.

Or, instead of negate(), you can reverse the subtraction... var dir = collidedMesh.getAbsolutePosition().subtract(camera.position);

You would do this direction-deriving... inside of your onCollide func.  (You probably knew that already, but future readers might not.)

And, you already know about scaling a vector3, so you know how to amplify or reduce the magnitude of that direction vector.

Our lights have a .setDirectionToTarget(), useful for directional and spot lights.  It uses the same positional subtraction method. 

Hope this helps.  Hope I didn't tell you anything incorrect.  :)  Congrats on the successful PG tests... well done.

Link to comment
Share on other sites

Well, so far it looks like this: http://www.babylonjs-playground.com/#12VV1R#1

I also attached WASD controls and free mouse look (without holding left mouse button).

I also made an actor (camera.ellipsoid) taller for the better view.

Also I decided to divide a player's impulse by mesh's mass. It's more correct way according to conservation of momentum law.

Thanks for help!


Realized, that this still is no good, it flies to wrong direction when I go left, right or back before collide it.


Link to comment
Share on other sites

Glad to say, that I improved my demo.

I just introduced a so-called kick-height. It's a height between foot and ground when an actor kicks mesh.

It made interactions more realistic and correct. It also fixed some bugs in vectors computations.

Here is current example: http://www.babylonjs-playground.com/#12VV1R#2

One last thing that distubs me a little bit is jolting when I continously push the mesh in one direction. 

However, maybe it can be fixed by adding throttling for onCollide handling on every particular mesh.

I'll try to find out what else I can do.

Link to comment
Share on other sites

Hi again Splash.  Congrats on the improvements... well done!

Let's go back to our no-physics "barrels test scene"...


After load, hold the up-arrow... keep pushing against that somewhat-buried-in-ground barrel2.  See the jiggling after collide?

It is MY theory... that these camera climb-over attempts happen... because the center of the camera.ellipsoid... is some amount higher (more +Y) than the barrel2.ellipsoid.  The camera.ellipsoid is trying to climb-over the barrel2.ellipsoid.  The camera.applyGravity is fighting-with those attempts.

Let's run a test.  Look carefully at lines 251-254.  That code waits about 16 minutes and then disables camera.applyGravity.  CHANGE that 1000000 to be 1000, and run again.  Then it will disable camera.applyGravity after ONE second.

Try your held up-arrow test again.  See how the camera.ellipsoid climbs-over the barrel2.ellipsoid?  Camera does not return to ground after climb-over because camera.applyGravity is disabled.

Climb-overs, dive-unders, and sideways scrub-offs... happen when two .ellipsoids get pushed-together... when their .ellipsoid center positions don't match.  For example:  IF the camera.ellipsoid center is higher than barrel2.ellipsoid center, then the camera will try to climb-over.  HOW MUCH mis-alignment is needed before a climb-over, dive-under, or side scrub-off happens, you ask?  Good question.

There is a property called engine.collisionsEpsilon.  I'm quite sure... THAT value... determines the amount of ellipsoid mis-alignment that is needed... before any "scrub-off" happens.

SO, what causes the jiggling/jumping?  You have probably already deduced the answer.  The camera is TRYING to climb-over our low-positioned barrel2, but camera.applyGravity is pulling the camera back to the ground.

Solves:  Good question.  Certainly play-with the value of engine.collisionsEpsilon.  Also think about possibilities of disabling camera.applyGravity inside-of onCollide, but re-enable after collision condition is cleared  (IS THERE an onCollideClear()?  Not sure.  Maybe there is an .isColliding or similar on the collider?)   Lastly, think about force-aligning the ellipsoids inside-of onCollide (by temporarily setting barrel2.ellipsoidOffset or camera.ellipsoidOffset... but that is probably not the best way).

Warning:  I'm not sure if .ellipsoidOffset is working at all.  In another test, I use the renderLoop to gently increase barrel2.ellipsoidOffset.x value (line 238).  You can see the ellipsoid move right, and the text read-out showing the collider's offset values.  As you can see with up-arrow tests, the collision is still happening AT barrel2 position.  This could be a bug in the framework.  Not sure.

I'm scared to report it as a bug... without others agreeing that it is broken.  I make many coding mistakes, and this could be another.  :)

Anyway, perhaps you have a bit more information, now.  If you do some tests involving someMesh.ellipsoidOffset, and learn good/bad things about it, please report them here, okay?  Thanks!  Be well.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...