I'm insane, please help me break your engine

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

I'm insane, please help me break your engine

Post by mcmonkey »

SO.
I want to update a single entity (a character), pushing it around the Space per normal, except completely off the main update loop.

Now, there are two ways to go about this:
1, the slow and boring way: Freeze everything, update the Space, unfreeze everything. That's not right.

2, the fast and fun way: Manually call everything I need to call to make the object fly forth. That's more my level of sanity.

So, this is what I've gotten so far:

(CBody is a CharacterController)
(TheRegion.PhysicsWorld is my ridiculously named Space object)

Code: Select all

                        ((IBeforeSolverUpdateable)CBody).Update(tstep);
                        CBody.HorizontalMotionConstraint.Update(tstep);
                        CBody.VerticalMotionConstraint.Update(tstep);
                        ((IForceUpdateable)CBody.Body).UpdateForForces(tstep);
                        CBody.Body.CollisionInformation.UpdateBoundingBox(tstep);
                        ((IBroadPhaseEntryOwner)CBody.Body).Entry.UpdateBoundingBox();
                        List<BroadPhaseEntry> bpes = new List<BroadPhaseEntry>();
                        TheRegion.PhysicsWorld.BroadPhase.QueryAccelerator.GetEntries(CBody.Body.CollisionInformation.BoundingBox, bpes);
                        foreach (BroadPhaseEntry bpe in bpes)
                        {
                            if (CBody.Body.CollisionInformation != bpe && TheRegion.PhysicsWorld.NarrowPhase.GetPair(CBody.Body.CollisionInformation, bpe) == null)
                            {
                                NarrowPhasePair npp = NarrowPhaseHelper.GetPairHandler(CBody.Body.CollisionInformation, bpe);
                                TheRegion.PhysicsWorld.NarrowPhase.OnCreatePair(npp); // I may have edited BEPU's source to expose this method, don't hate me, I needed it for a thing.
                            }
                        }
                        foreach (CollidablePairHandler entry in CBody.Body.CollisionInformation.Pairs)
                        {
                            entry.UpdateCollision(tstep);
                            entry.UpdateTimeOfImpact(CBody.Body.CollisionInformation, tstep);
                        }
                        ((ICCDPositionUpdateable)CBody.Body).PreUpdatePosition(tstep);
                        ((ICCDPositionUpdateable)CBody.Body).UpdateTimesOfImpact(tstep);
                        ((ICCDPositionUpdateable)CBody.Body).UpdatePositionContinuously(tstep);

So now I realize at some point I'm going to have to explain why I'm doing this...
This is actually a common thing to do when not using a physics engine. (And sometimes /with/ one, in cases like the Source engine!) It's a key point in properly transmitting a player's own movement across a network laglessly with client-side prediction. You have to move the player off-tick clientside to make it move to the correct location it belongs at.


So what's the problem with my code? MANY THINGS. But the problem I came here for specifically: The body will slowly fall into the ground, jump back up (as per the server's orders), then fall back in. It does so very slowly, very slightly, just enough to barely notice. I can almost ignore it and focus on more important things, but that'll rapidly get annoying with time.

Also the surrounding code doesn't seem to work much but that's my own problem, no need to worry you about it. I just want to get the player not having its feet inside the ground before I continue patching that up.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: I'm insane, please help me break your engine

Post by Norbo »

None of the character or collision constraints are ever actually solved in that code (just updated in preparation for solving), so they don't affect the involved objects velocities.

So, all that code does is integrate ballistic motion. Since collisions can't stop it, it'll accelerate through the ground until an 'actual' physics frame runs or it is snap corrected.

Going down this road will result in manually reimplementing a large fraction of what the space and its stages do. It doesn't actually avoid the complexity of the 'freeze the world' version, either. Consider what happens when a character hits another dynamic object. If the constraints are actually solved (as they must be to actually modify the character's motion), they'll also affect the motion of whatever the replayed character hit. In other words, if a hit object is dynamic, the prediction would affect the real world state. That's bad, so the hit objects would have to be made kinematic or there would need to be separate proxy objects that keep the prediction from affecting the real state.

It would be simpler to just create a 'replay' version of the space that includes proxy versions of the objects that you want to be considered in the replay. You may be able to get away with only the static environment. Maybe include kinematic proxies for other dynamic objects and characters with their motion in the replay defined by previously recorded positions. Or maybe the proxies could be dynamic too, it just requires some consideration for what produces a more accurate predicted position. Depending on game mechanics, you could probably prune out parts of the simulation that aren't in the immediate vicinity of the replaying character to reduce overhead. No duplication of the space's logic required!
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: I'm insane, please help me break your engine

Post by mcmonkey »

Oh, good plan. I'll try that.

... I have rather expensive-to-build objects ATM (haven't fully replaced the staticmeshes yet, that's still in-progress) what's the quickest way to duplicate a few staticmeshes? (I don't want to reconstruct from vertices, as that's expensive. Also, if at all possible, it'd be nice to have them share data. I already use too much RAM as it is, and these meshes are massive...)
That's irrelevant whenever I get my Voxel-based collision objects working. ATM, I have all the ray/convex traces and such functioning, however the character seems to get stuck against the surfaces (ground, wall, anything) rather than sliding freely against them. I have: a Voxel object, a Voxel shape, a Convex/Voxel pair handler, and a Convex/Voxel contact manifold.

A fix to either or both options will allow me to go forth and try your suggestion, which sounds solid enough for my immediate needs.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: I'm insane, please help me break your engine

Post by Norbo »

I have rather expensive-to-build objects ATM (haven't fully replaced the staticmeshes yet, that's still in-progress) what's the quickest way to duplicate a few staticmeshes? (I don't want to reconstruct from vertices, as that's expensive. Also, if at all possible, it'd be nice to have them share data. I already use too much RAM as it is, and these meshes are massive...)
To share all data between multiple StaticMesh instances in v1.4.0, you'll have to modify the source to allow sharing TriangleMesh objects between StaticMeshes. An easier option would be to just use the InstancedMesh type instead. It stores the hierarchy inside the shape, so there's virtually no overhead when duplicating. The InstancedMesh has to do a tiny bit more work during collisions, but it probably won't be noticeable.
the character seems to get stuck against the surfaces (ground, wall, anything) rather than sliding freely against them.
The pair material properties may not be getting zeroed by the character controller's callback properly. Check if the material properties are getting reset somewhere.

If the sticking only happens on borders between boxes, it may just be contacts being generated with normals which would never occur on a true continuous smooth surface, but are created due to the discrete nature of the individual boxes. That is, the character's toes might be hitting the side of a box in the ground that it's walking toward. Solving this problem isn't trivial. It's solved in meshes by using connectivity information to invalidate and correct contact normals (see the rather large TriangleMeshConvexContactManifold). Something similar could be done for the voxels, but it won't be easy.

If it happens everywhere, not just on boundaries, and it's not friction related, I'm not sure what is causing it.
mcmonkey
Posts: 92
Joined: Fri Apr 17, 2015 11:42 pm

Re: I'm insane, please help me break your engine

Post by mcmonkey »

Norbo wrote:To share all data between multiple StaticMesh instances in v1.4.0, you'll have to modify the source to allow sharing TriangleMesh objects between StaticMeshes. An easier option would be to just use the InstancedMesh type instead. It stores the hierarchy inside the shape, so there's virtually no overhead when duplicating. The InstancedMesh has to do a tiny bit more work during collisions, but it probably won't be noticeable.
Oh awesome, didn't know that existed. Thanks! That's perfect for temporary usage.
If it happens everywhere, not just on boundaries, and it's not friction related, I'm not sure what is causing it.
It happens literally everywhere (where there's contact, I mean), and adjusting the pairs friction allowed it to slide after a jump but rapidly freeze again. I'm going to play with it a while, and if I can't figure it out I'll come back here with a small sample app or something.


EDIT: Oh and I got the whole networked movement working via your method. a bit twitchy but that's entirely my end now. Thanks! :)
Post Reply