Collision Handling

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Arthur Gibraltar
Posts: 6
Joined: Sat Jun 23, 2012 5:01 am
Location: Brazil
Contact:

Collision Handling

Post by Arthur Gibraltar »

[Hello, Norbo! It's been a long time I hadn't programmed anything, but I'm becoming active again on C# and BEPU. I'm still pretty newbie, but I had some classes of Flash and C# in my college... The Flash is kind of useless for what I wanted. And I left college because I entered in a depression state and I'm taking some medicines until now for treating it.

I'm just posting this off topic message before going to my question because I'd really like to thank you a lot for your free physics system. Without it, I could do almost nothing about testing and creating a game. Your work is amazing. Thank you for sharing it! :mrgreen: ]

So, my question is about the Collision System. I'm starting to handle the events of the physics system. It's simple, but not for me: how to handle collision events? I need a piece of code.

My programming is a lot still based on tutorials and examples.

As you can see in my old topic: <viewtopic.php?t=1741>, I had many lag issues. I found it was because I was writing codes with memory leaks and loopings with always creating new objects. I'm pretty better on handling that now and searching for mistakes, but I still am not an expert on that.

I'm going to explain my ideas and my work state until now, in a shortened text, 'cause I really need suggestions. If you can give me, I'd really appreciate, as you are experienced on all this "coding world". :wink:

Going for the explanation, it's quite simple (but it's the only simple thing close to all that it's needed to be done): I really loved "Minecraft" and I'd like to make a game like it, free to build and destroy everything, but with good graphics. It's like that other game, "7 Days to Die", I guess, but I want more story and interaction, and more NPCs, like "Ragnarök Online", with even the "homunculi system" from that (sort of pets/assistants with an AI that protect and follow the player). It'll take a long time and many mistakes and tries, but I'm willing to wait and work all that I need and I may take all my life to build it, but I'll do.

All I got until now: I created the new project with some classes in which I can load a model and create bounding boxes and oriented bounding boxes which can rotate, from a Microsoft example. And the project has your physics system implemented. The class still has BEPU boxes for each mesh the model has, calculating its max and min vertices.

And as I need millions of boxes, I don't have resources to keep everything active all the time. So what I'm doing now is (or what I'm trying to do now): I deactivate and remove boxes from the Space when they are not needed (no dynamic boxes near, or when there's no movement/velocity) and I activate and add boxes to the Space when needed (when they are moving or near another box, or another box is coming to collide with it).

The problem is: I can't use the handling event systems yet, I never used it until now. The only thing I know how to do is write "BEPUbox.CollisionInformation.Events.DetectingInitialCollision +=", but I don't know what to write next. Would you help me? :roll:

After that, I'm going for programming a sky box, as I need to try new things on the project.

Thanks, again, Norbo, you are unique. :P
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Handling

Post by Norbo »

I'm just posting this off topic message before going to my question because I'd really like to thank you a lot for your free physics system. Without it, I could do almost nothing about testing and creating a game. Your work is amazing. Thank you for sharing it!
Glad it's working for you :)
So, my question is about the Collision System. I'm starting to handle the events of the physics system. It's simple, but not for me: how to handle collision events? I need a piece of code.
...
The problem is: I can't use the handling event systems yet, I never used it until now. The only thing I know how to do is write "BEPUbox.CollisionInformation.Events.DetectingInitialCollision +=", but I don't know what to write next. Would you help me?
A function which handles the event needs to be supplied. The function's signature must match the event.

DetectingInitialCollision expects a delegate with this signature:

Code: Select all

public delegate void DetectingInitialCollisionEventHandler<T>(T sender, Collidable other, CollidablePairHandler pair);
(Note: you can see the full set of collision event types in the CollisionEventTypes.cs file.)

The 'sender' parameter has a generic type which lets this delegate be used by different kinds of event systems. When dealing with entities, T will be an EntityCollidable. When dealing with static stuff like the StaticMesh or Terrain, it will be a Collidable.

So, you could make a function like this:

Code: Select all

        public void HandleInitialCollision(EntityCollidable sender, Collidable other, CollidablePairHandler collisionPair)
        {
             //... do stuff!
        }
and then write:

Code: Select all

BEPUbox.CollisionInformation.Events.DetectingInitialCollision += HandleInitialCollision;
Watch out, though. Collision events with present-tense names are 'immediate' events. That is, they execute as the engine executes. This makes a lot of operations unsafe. Adding/removing entities from within that handler, for example, would be like pulling the rug out from under the engine as it's running. In addition, if the engine is using multiple threads, the handler may be running on a different thread and you'll have to be careful to avoid unsafe asynchronous access.

In contrast, collision events with past-tense names, like InitialCollisionDetected, are 'deferred' events. These handlers execute sequentially after the end of the physics update on whatever thread called Space.Update, often making them easier to deal with.

For a working example, check out the FishInABarrelDemo in the BEPUphysicsDemos. For more general information, check the events documentation.
And as I need millions of boxes, I don't have resources to keep everything active all the time. So what I'm doing now is (or what I'm trying to do now): I deactivate and remove boxes from the Space when they are not needed (no dynamic boxes near, or when there's no movement/velocity) and I activate and add boxes to the Space when needed (when they are moving or near another box, or another box is coming to collide with it).
While limiting the number of individual objects floating around the broad phase is indeed a good idea for performance (especially in voxel games where there could otherwise be many millions of boxes), there are some fun related things I'm looking at for the next year or so of BEPUphysics. One of the improvements should make having a few hundred thousand static/inactive objects in the broad phase at once a non-issue :)
Arthur Gibraltar
Posts: 6
Joined: Sat Jun 23, 2012 5:01 am
Location: Brazil
Contact:

Re: Collision Handling

Post by Arthur Gibraltar »

Thank you, with your tips, it's working perfectly now. I can find the events' signatures with the "Go To Definition" option in the Visual Studio menu and create the handlers for them with the correct delegation. :)

Now I successfully am able to detect when a box collides and then remove it from Space as it no longer is floating or moving.

But I got a new problem. I searched the events BEPU can send to me, and I need some that show me when the entity has stoped, like if it had linear velocity and angular velocity equal 0, so I can freeze it. But none triggered with the data I needed. Until now, I can unfreeze a dynamic or kinematic Box if any dynamic Box is near, so it is added again to Space, for doing the right collisions. But I can't check correctly if the dynamic Box has stopped, so I can freeze everything again.

First I tried the isActive boolean data, but it's always Active, even if the dynamic Box has stopped on the ground. Then I tried the Collisions Events, and they work fine, I can freeze the Box when it touches another Box, but it's still not right: the Box should bounce a little before it gets frozen.

And now I tried the event of Position Changed, but I got no clue what's happening with the Velocities of the sender, nor about the positions it gives me: sometimes it has the same position from before even if the Box is still falling, it's weird. What should I do?

By the way, another subject: now I'm starting to work with your Threading feature, which I believe is awesome. And 'cause it may help me to not lag the game as I'll have tons of boxes active, and if it's a multiplayer game, I don't know what I'll do yet. And I tried to use the following code I copied from my project:

Code: Select all

IParallelLooper spaceThread; public IParallelLooper BEPUspaceThread { get { return spaceThread; } }
private Space space; public Space BEPUspace { get { return space; } }
// [...] Some other codes.
protected override void Initialize() {
    //  TODO: add your initialization logic here.
// [...]
    spaceThread = new ParallelLooper();
    space = new Space(spaceThread); //  Usar Thread?
Are the constructors right or did I miss something?

Anyway, thank you for everything! I'm loving all this. :D

Sorry I write too much, it's just I have so many things I don't know yet, and I'll wait my depression treatment to make some more progress until I go back again to a programming course.

I tried to search the forum, but there are too many messages. If I repeat something that already exists, I can use just the link for it so you don't need to waste your time rewriting an answer. :) [Sorry if I do that.]
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Collision Handling

Post by Norbo »

But I got a new problem. I searched the events BEPU can send to me, and I need some that show me when the entity has stoped, like if it had linear velocity and angular velocity equal 0, so I can freeze it. But none triggered with the data I needed.
If your goal is performance, the engine already has an efficient deactivation system built in. It will put unmoving objects into a low-resource-using state, and wake them up when necessary. I wouldn't recommend trying to create another fine-grained deactivation system for speed reasons. It would probably end up being slower.

If you have a world that contains a lot of inactive dynamic objects (say, 10,000 or more) and you want to help the engine deal with it (at least until the broadphase gets rewritten such that it doesn't matter anymore), I would recommend just removing entities that are far from any player from the simulation and adding them back in when a player comes near. A radius of a couple hundred units might work well. To make it a little fancier, you could avoid doing the removal until after the entity.ActivityInformation.IsActive is false. That ensures falling objects don't jarringly disappear just because they got far away.
First I tried the isActive boolean data, but it's always Active, even if the dynamic Box has stopped on the ground.
If it is truly still but refuses to go to sleep, something may be keeping it awake. Setting some entity properties like velocity and position or using ApplyImpulse will force the entity awake.

Another possibility is tuning issues- if the box and world are enormous relative to the default tuning parameters, even extremely small apparent velocities will be larger than the default sleep thresholds. This would be a concern if the objects are something like 1000 units across.
And now I tried the event of Position Changed, but I got no clue what's happening with the Velocities of the sender, nor about the positions it gives me: sometimes it has the same position from before even if the Box is still falling, it's weird. What should I do?
I'm not entirely sure what you're seeing, but note that entity.PositionUpdated will not fire for deactivated entities. Further, a deactivated entity is allowed to have some small velocity left over.

If the reason for removing-on-deactivation isn't performance but rather some game logic on deactivation, you can use the Entity.ActivityInformation.Activated and Deactivated events.

Watch out, these events are like immediate collision events- they occur while the engine is running. If you want to add or remove the member.Owner entity associated with one of these events, you'll need to add it to a thread safe queue to handle after the space update.
Are the constructors right or did I miss something?
The IParallelLooper needs to be told about the threads it can use. For example, from Demo.cs in the BEPUphysicsDemos:

Code: Select all

                for (int i = 0; i < Environment.ProcessorCount; i++)
                {
                    parallelLooper.AddThread();
                }
Post Reply