How to create explosions

click on the torus knot : Babylon.js Playground

2 Likes
  1. Sadly no. I guess you could maybe find a shader from the Shadertoy website and use that in this case
  2. Oh yeah, absolutely. The physics helpers on its own use the exact same feature (native collisions) to get the intersecting meshes. Strange, your PG example works fine for me. The most inner sphere is red, the second one inside it yellow, and the outermost 2 are green
  3. Honestly, I’m not that good in math either. If you check the physicsHelper that I wrote, it’s for the most part just very simple stuff in there. And yeah, as you’ll see there, for each effect I added only simple shapes (sphere & cylinder), as it was primarily meant to do those simple stuff and also for the sake of performance.

Yes, using a custom shape/mesh was also on my TODO list, but didn’t yet have time to implement it. So if you’re up to it, you can create a PR :slight_smile:

If you try this?
npm install git://github.com/BabylonJS/Babylon.js.git#master --save

2 Likes

Maybe something like this? https://palmer-jc.github.io/scenes/blow_me_baby/index.html

1 Like
  1. The most left sphere should not be green, it should be white because it’s not even intersected. But damageSphere.intersectsMesh() thinks that it is intersected.

Seems like a bug, but not really sure yet on which part. I’m using the same method (intersectsMesh()) in the physicsHelper and it works fine there.

I would do something like this;
uncomment line 60 to see the magic
https://playground.babylonjs.com/#HTV1TD#2

Simple distance check if within explosion range, then cast a ray to the target and look for any explosion blocking meshes, note of course, that a single ray is not very accurate, even if the “explosion blocker” doesn’t cover the entire mesh, but just the small path of the ray, it will still return as blocked, for more accuracy, you can add multiple rays where target vector3 is calculated based on target mesh’s position, size, etc, e.g. position.y + half size.y = head location,

side-note, intersectsMesh() was not working properly because it was running before scene was rendered, same issue here: Odd Ray behavior

2 Likes

Wow! Great idea! Thank you!

So, only shockwave blocking is left.

I continue to work with explosion. Now I am in a process of creation of so called chain explosions.

I created an algorithm: https://www.babylonjs-playground.com/#3GBTN9#1 (press ‘spacebar’ to launch the chain).

I want to discuss this algorithm, but unfortunately I am faced with a bug that could be reproduced only in playground. There is no such bug on my local machine with the same algorithm.

I am receiving ‘Uncaught TypeError: Cannot read property ‘dispose’ of undefined at babylon.js:16’. It’s trying to dispose eventData.sphere that doesn’t exist anymore. I believe it might be connected with some sort of garbage collection issues.

Key points of the algorithm (very briefly, will explain more when bug will be fixed):
class DestructibleObject:
An instance of this class should be assigned as property ‘destructibleObject’ to an object that we want to mark as destructible. But it’s necessary to make it properly.
Wrong: myObject.destructibleObject = new DestructibleObject(...args)
Correct: use createFromObject method from DestructibleObjectsManager class.

class DestructibleObjectsManager:
Tracks all destructible objects in scene. Removes object when destroyed.

class ExplosionManager: executes and debugs explosions. The main thing here is createExplosion method that receives the collection of destructible objects on the scene as one of arguments. What’s going on inside:

  1. Physics is created (using this.physicsHelper.applyRadialExplosionImpulse(...)).
  2. Casting the ray to every destructible object that were received as argument.
  3. Getting picked objects with ray (this.scene.multiPickWithRay(ray)).
  4. An array of picked objects should be cleaned from ‘explosion transparent’ objects and sorted by distance (_cleanHitsArray method is for it).
  5. Getting the closest object hit by ray (_getClosestHit method is for it)
  6. Calculating damage to the object that we picked. We are using linear falloff to calculate splash damage.
  7. Here are 3 important checks for the picked object:
  • Is it destructible object?
  • Is picked object is an object the ray was cast to. Here we are checking that we hit the target object on the ray, not any other destructible object on the way.
  • Is it not in explosion stack already?
  1. If all checks are true, then we put picked object in explosion stack with corresponding damage that will be applied later.
  2. Process the explosion stack.

I don’t like how I organized and execute explosion stack. It has some issues. But I need to find a way how to avoid the bug in playground that I mentioned above before I continue. Please help with a bug.

I haven’t fully checked the code yet, but I think the issue is you disposing the impostor & shape/mesh before the actual explosion event? Inside the redBarrelDieHandler, if comment out the disposes there it works. Or maybe just move the disposing after the event?
The thing is, that the shape (explosion sphere) will be auto disposed with a delay (it’s inside a setTimeout()), in case you still want to use the sphere for your own stuff in the current tick, so you don’t need to manually dispose it.

I don’t think that this is the reason, because:
a) Explosion doesn’t need mesh or impostor, it requires only position vector. I intentionally delete mesh and impostor of the barrel before creation of explosion on it’s spot. It’s necessary to exclude that barrel from destructibleObjects in order to reduce the cycle and eliminate some glitches like self-intersection.
b) If I comment out the disposes nothing changes for me. I am still getting the same error in console.
c) My algorithm doesn’t cause same error on my local machine. I am receiving this error only in playground.

FYI @Deltakosh The playground https://playground.babylonjs.com/index.html#0LM7CJ#6 doesn’t work any more because the data.rays from showExplosionDebug don’t exist any more in the newer BabylonJS release. (I had the same error in my own code, and updated my code to not process rays field.) Loved the ray-functionality though for physics debugging…

Yeah, I know. I removed the rays there as I wasn’t really sure that it would be really used and had a performance cost with some events (such as the updraft & vortex). That’s the new PG with all the effects now: Babylon.js Playground

So this one doesn’t work for you?
https://www.babylonjs-playground.com/#3GBTN9#3

It does fix the error for me

Did you find it in the doc?

1 Like

Now your link is working for me, maybe I just commented something wrong last time. Thank you! However I still don’t understand, how explosion debug sphere that uses only explosion data may be connected with disposing of the mesh that was used only to set position of explosion? And why this happens only in playground?

Please help me with graph theory while implementing explosion chain.

To understand my examples, please open console and take a look at these strings: ‘applyDamage {current_detonating_barrel} {damage_amount} EN:{previous_barrel_in_chain}’. In both cases detonation starts from _5 barrel. Press spacebar to launch chain reaction.

Explosion chains work good for binary trees: https://www.babylonjs-playground.com/#3GBTN9#5
It goes consistently through right branch and after that through left branch. All branches start from _5 root node and damage for closest neighbours (_6 and _4) is calculating from _5 barrel also.

For N-dimensional tree it works much worse: https://www.babylonjs-playground.com/#3GBTN9#6
It goes consistently for _t branch (the bottom one) and then barrels from _t branch trigger barrels from left and right branches. See the red arrows on the figure below.

But I want it to go consistently through all branches one-by-one like it shown by black arrows. I don’t want that ‘red arrows’ intersections. It causes wrong damage calculations.

Possible (but not really good solutions):

  1. Using current barrels positions, build actual N-dimensional tree instead of explosion stack. Then calculate detonation order using in-depth traversing of the tree and then detonate barrels according this order. But such a priori approach doesn’t assume that all current barrels positions might be completely messed up after first explosion. This will be especially notable if we will decide to detonate barrels after delay (fire it up first and then explode like it was in Half-Life). We need onflight recursive solution.
  2. Reduce radius and arrange barrels so the one barrel could trigger only the closest barrels. Ad Hoc solution that doesn’t fix algorhitm itself. Also other barrels can be moved closer after previous explosions.

Please help to understand how to fix this algorhitm.

1 Like

I would interpolate random linear vector for debris position. But beyond that…nvm 12345.

Hi there @splash27

The Double Buffer may be an option to fix your problem with interdependent iteration over collections (like exploding barrels). Scroll to the ‘slapstick comedy’ section, which is an example like exploding barrels igniting each other but then with players slapping each other.

http://gameprogrammingpatterns.com/double-buffer.html

You can read the coding technique online for free (and buy the book if you like it…)

1 Like

I
DID
THIS!

https://www.babylonjs-playground.com/#3GBTN9#7

I wasn’t able to use double buffer directly, but this inspired me for some ideas.

I converted my linear damage stack into this:

/**
 * this.damageStack[0] - readStack
 * this.damageStack[1] - currentStack
 * this.damageStack[2] - nextStack
 * */
 this.damageStack = [];

Read stack keeps only DestructibleObject instances, current and next stacks keep DestructibleObject and args array with damage and other data that might be transfered to applyDamage method (debug data in our case).

Important! We are not creating such structure initially. The current number of existing inner stacks is also important flag that allows us to determine on which stage we are.

The basic idea is:

  1. If there is no inner stacks we can write all affected barrels directly to read and current stacks to save one iteration (Line 322).
  2. If current stack is not empty then affected barrels will be placed into next stack (Line 330). But this will happend only if there is no such destructibe object in read stack. There is no need to add to next stack a barrel that will be exploded in current stack or already has been exploded earlier.
  3. If affected barrel is already in current stack we are updating future damage for this barrel in current stack (Line 317). This is it! This is how damage transition goes through chain. The barrel will receive damage from the nearest barrel in the chain, not from the barrel that firstly affected current barrel.
  4. After all reachable barrels were placed in the next stack, this._processDamageStack() call occurs. This method does shift() from current stack and applies saved damage this may cause new explosion.
  5. If damage wasn’t enough to make new explosion we have a special checking (Line 247) that will force going through current stack if nothing has been exploded.
  6. After all barrels from current stack will be handled, the this._squashDamageStack(); call occurs. This method remove duplicates from next stack saving the biggest damage and puts it as new read and current stack.
  7. If nothing has come to new read/current stack, then all chains are finished (Line 258).

If you will open console, you will see that all barrels will be exploded with the damage from the closest barrel ignoring the barrel that put current barrel to the stack.

Possible performance boosts:

  1. Args array. Since our algorithm ignores the order of adding to stack now we can remove the adding of sourceExplosion to args array (Line 311) which was used for debugging purposes. This allows us to remove one layer of array. This will be good for performance.
    Again, we are not tracking chains we are only delivering damage through it.
  2. ES-6 slow methods. I used reduce method and Map object in squashDamageStack() for readability, but these approaches are relatively slow. Direct array traversing might work faster, despite it will require writing more code.
  3. Turn off debugMode flag in ExplosionManager and DestructibleObject classes.

What’s left:

  1. Visualitation of explosion. Nothing is done here.
  2. Walls should block shockwave. Splash damage through walls already will be blocked in my algorithm. But there is nothing I can do with physical shockwave (that pushes object). I thing this could be fixed only inside Babylon.
  3. The checking on line 247 works for barrel chains but it is not universal. What if something will be destroyed without explosion on it’s death. Will do more investigations here. Stay tuned.

So what do you think about my solution?

EDIT:
I decided that in my gaming world the higher damage in chain will override the lower one. But you can accumulate it instead. This will require pretty obvious changes on lines 215 and 318.

2 Likes

Nice one! As for the physics shockwave - if you want, you can just easily take the relevant bits out of the physicsHelper, and integrate only the stuff you need for your ExplosionManager. For the most part, it’s just simple stuff in there. I will probably be far more efficient, as it now needs to calculate some stuff twice (intersections & raycasting for the same objects).

1 Like