Jump to content

How to make mesh move along the ray or curve?


Recommended Posts

Hi, everyone!

I am about to implement bullets ballistics.

The first question is how to make mesh (bullet, rocket or whatever) move along the ray emitted from first person perspective?
The second question is how to do the same but along the curve? It's necessary for grenade launchers or for realistic bullets behavior. In real world it flies along parabolic curve.

Does anybody have detailed examples with explanations?

Link to comment
Share on other sites

Hi splash!  Quick comment... this might be a perfect application for a physics engine and Babylon's cool interface/plugins for it/them.

Talking about bullets...

ApplyImpulse() or applyForce() commands could be directly linked to powder loads/types.

Spin the bullet as needed... using rotational velocity, matching the rifling spirals of the barrel, as wanted.

Muzzle velocity measuring is as easy as getLinearVelocity(), plus use it to get projectile velocity at any "time" during the flight.

Gravity works just like Earth gravity, or do your shooting on the Moon or Mars, easily.  Engine will automatically calculate/cause the correct parabolic-curved bullet drop, based upon velocity, bullet mass (grain), and air resistance.  Nice, eh?

Air resistance is NOT something calculated by the default physics engines, but the fine people who developed BJS physics plugins... created a setLinearDamping() that is PERFECT for wind resistance, and might even work for encountered-during-flight rain drops and snow flakes.

These same forces/calculations (all nicely done FOR you) would apply to ANY projectile... bullet, mortar, rock... and arrows/missiles to a degree.  (Finned/foiled/fletched things could be a bit rougher, needing advanced airfoil calculations, of course.).

There are apropos reasons why these 3rd party physics engines all have "ball-istic" names such as... cannon, ammo/oimo, bullet, energy, etc.  :)

Just some thoughts.  A playground search for setLinearVelocity, applyImpulse, physicsImpostor, etc... should bring lots of returned physics demos.  Some of the PG demos haven't been updated, and still use setPhysicsState().  With a little fiddling around, they can be updated to the new mesh.physicsImpostor = something method.

Hey, there's JohnK... I hope he's doin' good.  Recently, he, with little help, did a complete overhaul of our tutorials and help sections, and did it marvelously.  (hugs)  He's so cool it's ridiculous!

Anyway, yeah, Splash... I think you owe it to your brain... to consider physics engines for this endeavor.  Party on!

Link to comment
Share on other sites

Thanks.  Yeah, we're still fairly buried in snow, but headed for 50f+ today.  Slush everywhere, now.  I think I saw a fish swimming across the mail-person path, earlier.  :)  Appropriate to the thread starter... it "splashed" a little when it had to swim thru some "deer beans/peanuts" that were deposited there last night.... by other wildlife.  :)

Splash is cool... he doesn't mind if we talk about the weather in his thread.  But, I think he draws the line at ... farm-animal love-making talk, though.  ;)

Link to comment
Share on other sites

Hi S.  I'm only visiting to drop a playground on you... https://playground.babylonjs.com/#0H29AJ#17

I dunno who did it... but it's physics-active and there's some strange Quaternion stuff in there.  Essentially, click on green ball to pick it up.  QEWS keys do SOMETHING rotational at that point... not sure what.

Space to fire the 'pickup'.

@RaananW has a fine basketball game... too... with camera-aimed physics impostor.  http://raananweber.com/basketball/

You'll likely need to run his code ( http://raananweber.com/basketball/main.min.js ) thru a JS pretty-fier... to better see how it's done.

I might be able to help more... after the weekend.  Right now... I'm soakin' up some sun and warmth... watching snow-melt run-off from the local hills.  It's a nice time of the year (with low/no bugs) to be anywhere except camping under this winter haystack.  :)  (got bad cabin fever - it was a lonnnnnng winter).

Good luck, hope this helps a little.  Talk again soon.  Stay tuned for others, too.

Link to comment
Share on other sites

Faced new problem.

Here is a function that spawns a projectile near player's camera, calculate a vector between point of view and placed projectile and launch the projectile to the flight.

launchProjectileInstance(actor) {
        let instance = this.projectile.createInstance();
        instance.parent = actor.playerCamera;

        instance.position = new BABYLON.Vector3(0, 0, 1.5);
        instance.rotation = new BABYLON.Vector3(Math.PI/2, 0, 0);
        instance.isVisible = true;
        instance.physicsImpostor = new BABYLON.PhysicsImpostor(instance, BABYLON.PhysicsImpostor.CylinderImpostor, { mass: this.projectileMass, restitution: 0 }, this.scene);

        let movementDirectionVector = instance.getAbsolutePosition().subtract(actor.playerCamera.position.clone());

The main problem here is

instance.parent = actor.playerCamera;

This string destroys physicsBody of instance and the app crashes at setLinearVelocity with error: "Cannot read property 'velocity' of undefined".

How can I place a projectile relatively to player's camera?

I tried something like this, but this worked incorrectly:

instance.rotation = actor.playerCamera.rotation.add(new BABYLON.Vector3(Math.PI/2, 0, 0));
instance.position = actor.playerCamera.position.add(new BABYLON.Vector3(0, 0, 1.5));


Link to comment
Share on other sites

I agree.  I already had one half-done, so I advanced it.


In general, maybe it is wise to use...
   bullet.translate(axis, amount, LocalSpaceOrWorldSpace)...
to position mesh with physicsImpostors. 

Sometimes, you might need to do three of them (one for each axis)... to fully position your physics-active mesh (call them p-mesh if you wish). 

You might need to set bullet mass = 0... to prevent falling.  Just before firing... bullet.physicsImpostor.setMass(1.0), perhaps.  *shrug*

I didn't use any translate() in the above PG.  What I did... is parent the bullet to the cam... just like you did, Splash.  That makes the bullet aim-able WITH the camera, as you know.

BUT, I didn't add the bullet's physicsImpostor... at bullet creation time.  I wait until moments before shooting... to do that.  :)

Let's look at the "shoot" code in lines 73-84.  I kill the parenting, then add impostor, and then launch.  Works pretty good.

Although freeCamera uses its .target differently than Arcs do, its target is VERY handy for deriving a camera direction, which works fine for the bullet's linearVelocity direction vector.

Some problems
      - Don't HOLD the space bar when shooting.  Just a quick tap, works better.  This PG needs some better keypress-listening... perhaps using observers.

      - This has some classic physics engine "ball-thru-wall" problems.  This might be correctable by up-scaling everything (make everything larger), and/or by changing the world step speed.  scene.getPhysicsEngine().getPhysicsPlugin().world.timeStep = .08;  (maybe)  (no promises).  :)  There is also a world scale setting, I believe.  It relates to the sizing issue I mentioned, I think. 

      - When bullet DOES rebound from target (rare), it won't "sleep" after it stops rolling.  Instead, it begins/does some continuous slow rolling and colliding.  I don't know why.  Possible bug in Cannon plugin.  Possibly, excessive restitution-related "Brownian jitter" (constant vibrating due-to continuous ground->sphere collision), and maybe physics world .allowSleep needs setting true.  Perhaps our ground planes have a small, unwanted x-axis tilt/angle, for some reason.  hmm.

Physics engines are picky little bastards, sometimes... but... they can be tamed... often via terrorizing/threatening them with sanctions.  hehe... ahem... sigh. 

This is ONE method of 'hovering' your bullet in-front-of camera view... until firing.  There may be other/better ways. 

I hope this helps.  It should work fine as a basic testing playground, at least.  Would the function to calc force/speed... be called...  figNewtons() ?  Ar ar ar ar!

Link to comment
Share on other sites

I implemented it as it implemented now in my app. Here is playground: http://www.babylonjs-playground.com/#RS8SCE

The trick with instance.setParent(null); works. 

However, there is another problem. The projectile with zero mass will not fly. I want to make a rocket that will ignore gravity, however I want to keep gravity working for another physical objects that may be placed into the scene.

Is there a way to exclude gravity affection for particular physical object? As I mentioned before, setting mass to 0 doesn't work.

Link to comment
Share on other sites

How about NOT installing a physicsImpostor on the rocket, and fly it via mesh.translate and/or via lerp?  Would that work?  With a good mesh-mover formula, you could still simulate (fake) acceleration, and simulate reduced air-resistance at higher altitudes.

But why not make it act like a real rocket?  Leave rocket gravity ON and mass ON.  At engine start-up, use repeated little .applyForce() or .applympulse()  [use no setLinearVelocity].

Repeated little applyForce() and applyImpulse()... will accumulate and slowly/gently increase rocket linearVelocity.  Very realistic.  Physics engine calculates velocity/acceleration.

You can also use setLinearVelocity(), but start tiny... and gently increase it across time/altitude.  This method is much more fake/non-realistic.  Programmer fakes velocity/acceleration.

Try some repeated upward applyImpulse/applyForce (in the renderLoop or with onEveryFrameObservable)... upon the physics-active rocket.   I think you will like it.

Link to comment
Share on other sites

What about gravity force compensation? Will it works? I want to applyForce to every projectile instance. The force will be equal to gravity however it will be directed to opposite direction.

I try to add this after setting linear velocity:

instance.physicsImpostor.applyForce(new BABYLON.Vector3(0, 10, 0), instane.getAbsolutePosition());

However I can't see any changes. How applyForce() works? Will the force be applied forever (like gravity) or it will be applied only during first physical step(s)?

Is it possible at all to compensate gravity during all lifetime of the mesh (impostor)?


PS: How to change the title of this topic? I want to make it more related to projectile ballistics.

Link to comment
Share on other sites

3 hours ago, splash27 said:

PS: How to change the title of this topic? I want to make it more related to projectile ballistics.

Edit your first post in this topic and you can also then edit the title. However I would suggest you would be better off and possibly get more replies by starting a new topic with the question you now want to ask plus a PG illustrating the specific issue. Even if you change the title hovering over the title will only bring up your first question.

Link to comment
Share on other sites

I did it! Almost at least.

My solution is here: http://www.babylonjs-playground.com/#RS8SCE#1

I just calculate the final destination of the projectile and use Animation to make it move from spawn point till the end point. I also destroy projectile after maximum distance travelled (mind the memory, huh).

However, there is still a problem. I can't detect the collision between projectile and any other mesh during the flight. This doesn't work for some reason:

instance.onCollideObservable.add(function (mesh) {




Link to comment
Share on other sites


I had to make a few adjustments to make it work for me.

BUT, by using animation, you lost all the cool stuff from the physics engine... like math-calculated projectile drop, and velocity fall-off (if there is some).

If you wanted REAL math-calculated ballistics, you lost most of it when you switched from physics engine to forced animation.  Your call, though.

BTW:   instance.physicsImpostor.applyForce(new BABYLON.Vector3(0, 10, 0), instance.getAbsolutePosition());   // missing 'c' is problem, perhaps?

Watch your console.  :)

Also, I'm not sure if onCollide will be observed/processed during an animation run.  Did you try intersectsMesh too?  Just curious. 

I'll keep thinking... but... I think it would be MUCH cooler if you stay with physics engine.  Math-calculated ricochets are possible with physics engine, but not with Animation.

But yeah, your animation is working nice.  Pitchew!  :)

Link to comment
Share on other sites

Hi S.  Yeah, I got the same problems, plus a few more issues.


(spacebar fires the bullet)

Right now, I'm only working-on bullet reset (lines 92-106), trying to avoid re-RUNning the playground for every shot.

And, of course, in my FF, spacebar or cursor up/down... causes the playground app to scroll one line upward (creating a white line across the bottom of PG app)... and this one-line scroll causes all the GUI buttons at the top of the playground... to be half-hidden, making them difficult to use.  *sigh*.  It's driving me nuts on PG's that use spacebars and/or freeCam up/down cursors.  Erf!  I might need to switch to "F" for fire.  :)

And then... having the bullet go thru the target most of the time... sucks.  And onCollide... (lines 83-85) failing whenever it feels like failing... that's wonderful, too.  (not)

I really would love to see this project... continue to use a physics engine... because... then it becomes a REAL ballistics testing thing... something that could actually be used as a police/CSI investigative tool.  Bullet grains matter, powder loads matter, powder type matters, humidity/windage can be calculated and mathematically considered... a very accurate and realistic sim.

So, I'm calling-in @Raggar and @RaananW and any other physics Gods that want to offer input.  This should be one of the most-simple physics scenes in the world... to create.  Yet for poor Splash27... it has been a 3-week+ nightmare.  That's just terrible.  Sad.

Think about what he/she is trying.  Launch a simple round projectile, from camera to target, with onCollide indication.  How simple!  Why is it so problematic?  Worse than all this, we had the same issues with the ping-pong table/paddles, and that issue was never properly addressed.  Inconsistent/sporadic onCollide.  Physics world step speed, and world scaling... was suspected as possible causes, but nobody was able to show a PG with onCollide consistency (eliminating ball-thru-wall issues - one of the toughest physics-engine problems to beat, worldwide, I think.).

I AM doing a strange action... in this test PG.  We put NO impostor on the bullet... and parent the bullet to cam... until shot-time.  THEN, we kill the .parent, add a physicsImpostor, and setLinearVelocity to fire the bullet (lines 74-90).  Doing things this way... complicates the bullet reset code, of course... but it should NOT affect onCollide and bullet-thru-target issues.

When the ball/bullet DOES hit the target and roll to the floor at the target's base... why won't it sleep, or even sit still?  Strange!

As a reminder... use QUICK-tap of the spacebar.  Any significant hold-time on the spacebar... can cause issues. Adding controls.space = null; around line 75 should fix that.

Help welcomed!  Do we have a playground that shows this simple physics task?  I don't have one.  Meantime, I'm going to keep testing/trying.

Link to comment
Share on other sites

For the onCollide callback, you could always use the more hacky way of adding the event to the CannonJS body itself:

bullet.physicsImpostor.physicsBody.addEventListener('collide', function(){



Now, the issue with bodies going through walls/other bodies is the reason I changed from projectiles to ray-based shooting in my projects.

Take a look at the following issue:


With the following video of CannonJS with CCD implemented:

This ensures that bodies don't clip through other bodies between steps due to high velocities. I haven't tried it myself, but it's worth mentioning, if you feel like building CannonJS with those improvements.

Link to comment
Share on other sites

Thanks Raggar.  Your scene is definitely working perfectly.  Thx for the video!  Good links, too, thx.


I cranked-up the step speed in line 15... to about 8x default speeds.  Thru-target is working a little better.

I added an intersectsMesh tester in lines 92/93... it never triggers.  :)

Hmm.  If ball, visually, is seen hitting target and rebounding, onCollide HAS TO trigger, right?  SOMETHING made the ball rebound.

This seems to indicate that BJS.physicsImpostor.onCollide is incorrectly listening for collision events from the physics engine.  Inconsistent.

In other words... thru-wall is a physics engine issue, but there might ALSO be a BJS-PhysicsImpostor "listening to ACTUAL physicsBody" problem.   Two different issues, yet highly related.  hmm.

Link to comment
Share on other sites

Update:  https://playground.babylonjs.com/#0H29AJ#27

[f]ire button.  Yay!  No more spacebar to fire.  Use button or 'f'.

Currently working lines 90-102... ball reset... still screwy.  :)   I sure wish I had gunsmith experience.  :D

After that... I'm going to find a better-working collide-tester... even if it kills me.  heh.  I think Splash wants to turn-off the bullet after it hits the target, and perhaps put a little "hole decal" on the target at that time.  Perhaps a little puff of manual-emit-count particles... happening at the point of impact, too, eh?  ;)  Later, maybe two viewports, or a nearby plane with a renderTargetTexture showing a close-up view of the target?  Yeah!   A "watch the guts blurp-out-of the shot deer"-cam.  (ewww)

I'm seeing MUCH LESS bullet-thru-target, now.  In fact, I haven't seen ANY.  Coooooool.  Increasing step speed... might have helped.  One problem at a time. 

Link to comment
Share on other sites

I think the intersectsMesh issue is due to being checked only if the space/f buttons are pressed. Even if they ARE pressed, it still doesn't seem to register, but moving the check outside buttondown-check seems to work:


Edit: A little work on the reset:


It still behaves oddly if you quickly fire before the ball is reset, though.

Edit2: Might not be the best option, but this fixes the odd behavior for now:


Link to comment
Share on other sites

Yeah!... well done.  Dummy me.  :)

In fact, my else if... should be only IF... and the order of events needs to change a bit.  (check intersect before check reset bullet).


Very good.  We have hope!  thx for your work, R!  resetBullet() is still being annoying.  Thoughts? 

Currently triggered if ball hits floor altitude.  Maybe... put it on a 10-sec timer for fun, but later, Splash might reset bullet upon impact/intersect.

I want the timer... so I can experiment with some ricochet stuff, later.  :)

But right now... when bullet.parent is set back to cam during reset (line 100)... it still falls like it has physics, and it shouldn't.  Bullet.parent?  Bullet.setParent()?  Not the same, it seems... but that's not the problem.  Might need to dispose old bullet and barf-out a fresh one.

Verified:  https://playground.babylonjs.com/#0H29AJ#34

Dispose-to-reset works MUCH better.  Yay, no more pressing the RUN button over and over and over.  :D  Intersect is working SWEET now!

I think we're getting ready to fly some geese overhead, eh?  heh

Link to comment
Share on other sites

Okay, here we go with another...  https://playground.babylonjs.com/#0H29AJ#35

Added lines 73-83 ActionManager onEnter listener... on the target.

It works first time only... because of line 77 parameter.  It doesn't accept any, none, null, etc.  If it was set 'bullet'... that would also work first time.

I think this is because I am replacing the bullet object... during the bulletReset().  I thought I could work-around the situation... using look-up... ie. scene.getMeshByName("ball").  Nope.  :)

(Wingy dons his magician's outfit... because he needs to fool an actionManager, somehow.)  :)


Can always replace the target's actionManager every time the bullet resets.  :) Sneaky.  Works fine.  (watch console)

TWO working intersect testers!  YAY!  (Wingy dances around like an idiot).

Link to comment
Share on other sites

@WIngnut, @Raggar, thank you, guys!

I'll try to adopt your investigations to my case. I also faced the problem with bullet-thru-target issue on high velocities. I even thought about openning new topic for this :) Increasing physical timestep might help a little bit. However if I increase the power of the ball from 70 to 100 in Wingnut's last example, no further increasing of timestep helps. This is not a problem if I will destroy the projectile right after colliding, however for some other simulations this might be a problem.

Also, the issue with handling 'collide' event in animatable mesh (with no impostors) still remains. I posted PG with animatable rocket before:  http://www.babylonjs-playground.com/#RS8SCE#1

Btw, what is CCD?

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...