Physics: bouncing around INSIDE a ring


#1

I’m looking for an efficient way – using any physics-engine, really – to handle a simulation in which a ball is bouncing around inside a ring-shaped (mesh) object. The collision detection algorithms that I have so far seen assume that a collision occurs whenever the bounding-boxes of the objects overlap, but if the ball is on the inside of the object and trying to get out, that will always be the case.

My problem would be fairly simple if there existed a spherical collision-geometry that could be, so to speak, inverted. Another cumbersome idea that I had was to use compound objects, dividing the ring into many (convex) parts. But I think that I am over-thinking this thing.

Suggestions?


#2

Spherical collision is actually very easy to do yourself: just use the distance formula. And yes, it works in 3D:

public static function distanceBetween(p1:Vector3D, p2:Vector3D):Float {
    var x:Float = p2.x - p1.x;
    var y:Float = p2.y - p1.y;
    var z:Float = p2.z - p1.z;
    return Math.sqrt(x * x + y * y + z * z);
}

Now imagine two spheres in a 3D environment. You know where each sphere is, and you know each sphere’s radius. This is enough information to tell whether the two spheres are overlapping:

public static function spheresColliding(p1:Vector3D, r1:Float, p2:Vector3D, r2:Float):Bool {
    return distanceBetween(p1, p2) <= r1 + r2;
}

If their centers are close enough, they’re touching. Simple as that! Rotation doesn’t matter because rotating a sphere doesn’t change its collision. The direction from one to the other doesn’t matter because, again, they’re spheres.

Only their radii matter. Large spheres collide sooner, and small spheres collide later.


Aside: Math.sqrt() is relatively slow. If you square both sides of the equation, you can skip it entirely:

public static function spheresColliding(p1:Vector3D, r1:Float, p2:Vector3D, r2:Float):Bool {
    var x:Float = p2.x - p1.x;
    var y:Float = p2.y - p1.y;
    var z:Float = p2.z - p1.z;
    var r:Float = r1 + r2;
    return x * x + y * y + z * z <= r * r;
}

Again, your code will work either way. This is just for performance.


Ok, back to the main topic. It’s all well and good to tell whether two spheres are overlapping, but you asked about keeping one sphere inside another.

One solution is the one you suggested: !spheresColliding(). But the thing about that is, your ball will pass 99% of the way through the wall, only stopping the moment before it gets completely outside.

So you’ll need to modify your function a bit. Instead of testing the ring sphere as-is, pretend that the ring is smaller, so that the ball will stop sooner. That is, you want to subtract the ball’s diameter from the ring sphere’s radius: !spheresColliding(p1, r1 - 2 * r2, p2, r2).

Basically, you’re drawing an invisible sphere that’s just a bit smaller than the ring. Your ball must always touch this invisible sphere (even if it’s only touching at a single point).


#3

I’m now pondering how to implement this within the context of BabylonHX. It sounds like I will be using the physics engine but have to roll-my-own collider.

The object in question is a ball, and when it hits a ring it needs to bounce off, and to do so in a convincing way.

I’ve briefly pondered if I should try to “fake it” by creating a ring of spherical collision-shapes spaced equally around the ring but I guess I’m just going to have to roll my own collide-logic using the trigonometry you’ve suggested.

Any suggested code-samples (e.g. on GitHub or such) that I might wish to look at for study?


#4

Are you looking for something like that?

It is kha code but useful i guess:
hgppfb-kha/HGPPFB #0016

And i made it by watching this serie from tarik kaya.


#5

Well, that particular bit of source-code might be a bit too minimal to be useful in this particular context, but it definitely gives me some inspiration.

At this point, I have more-or-less decided upon the BabylonHX framework for this piece and am therefore looking for specifics.

Also, I should mention that the obstacles in question are nested rings, and that they are rotating while being attached to each other … exactly in the manner of a gyroscopic gimbal. And, this is of course a three-dimensional world.

It’s therefore not entirely a question of “how to do it,” but rather, “how best to do it.”


#6

Nested rings shouldnt be a problem when you make each ring and its content(inside stuff) relative to each other(offset x/y/z to the parent) - kinda recursive. and because they are rings/spheres, rotation doenst interfere with the bouncing behaviour anyway.

Advice after years of programming, dont concern yourself so much with a “best solution” before you even have a working one :slight_smile: Its easier and faster to optimize/rewrite once you made it work fully.


#7

Aye, aye, aye! “Old-Phart” also here! (Ahem … “these kids today” …) I read you loud and clear.