I did try transposing the order in which the centerPosition and centerOfMassOffset are serialized, but the result is the same. So it seems the write order does not appease.
I believe there is something hiding somewhere, obfuscated by the unintuitive properties. For example, this tiny piece of code works as expected:
Code: Select all
Box box = new Box(Vector3.Zero, 1, 1, 1, 1);
//Technically, the internalOrientationMatrix is equivalent to the orientationMatrix property here, since
//box does not yet belong to a space. When an entity does not belong to a space, buffered properties
//act like unbuffered properties. I don't like this inconsistent behavior either.
box.orientationMatrix = Matrix.CreateFromAxisAngle(Vector3.Normalize(new Vector3(1, 1, 1)), 46.1245267f);
box.centerOfMassOffset = new Vector3(1, 1, 1);
space.add(box);
//Now that the box belongs to a space, this value will be put into the write buffer to execute at the first frame.
box.centerPosition = new Vector3(0, 1, 0);
//If I check the centerPosition value here, it is (0,0,0). So is internalCenterPosition.
...
//In the update method:
//Still zero values before update.
space.update(dt);
//Both values now (0,.999..., 0).
//(Slightly less than (0,1,0) since it fell a bit in one frame).
There may be some legitimate write/read order that produces incorrect results, but I haven't encountered it yet. A reproduction case would help squish the bug if it exists.
I looked for 'internalCenterOfMassOffset', but there's isn't one. Did you forget to add the 'internalCenterOfMassOffset' property?
An internal version of that particular property would be redundant, because it is unbuffered to begin with. The confusion is understandable, given the names
Each property's associated XML documentation lists whether or not it is buffered/interpolated.
What happens if I need to use the threading features of BEPU? Since transposing the serialization of centerPosition and centerOfMassOffset does not fix the issue, am I unable to use the threading features at all?
All of the BEPUphysics internal threading can be used without worrying about using thread-safe properties (for the most part), since the engine follows a fork-join model where all threads are idle by the time the main thread exits the Space update. The only time thread-safe properties become truly useful is when the physics update loop is set up on a different thread and individual values need to be accessed asynchronously, which is quite rare.
To safely read more than a single entity's buffered property while the engine is running asynchronously (in rendering, for example), use the space's motionStateManager's getMotionStates method. This method handles buffer locking and atomically reads from a single frame, avoiding reading one entity's state from frame X and the next entity's state from frame X + 1.
Finally, I use the Vehicle and Wheel classes to do a lot of things. It does not expose any 'internal' properties. So I'm concerned that it forwards its property values to buffered properties.
None of the properties on the Vehicle are buffered in the same way entity properties are (i.e., they are not thread safe). However, various world space properties are updated as needed during a space update. The most important one for rendering is the wheel shape's worldTransform property. This is called at the end of each frame. Fortunately, the Vehicle class exposes the updateAtEndOfFrame method publicly, so you can call it whenever you want to force an update of the vehicle's wheel transformations.
The fact that nothing is buffered on the latest version of the vehicle is actually an oversight. The world transform should be protected in some way to prevent ugliness when running asynchronously. I'll take a look at this when I can.
In this mode, I can only drag the shell of the car as neither the wheels nor the (most importantly) bounding box will update.
Entities have a forceBoundingBoxRefit method that can be called. It will not automatically update collision pairs, though. The space's broadphase exposes an updateCollisionPairs method if needed. The upcoming rewrite will also make it easier to use the other stages, like narrow phase collision detection, externally.
This is an issue since the editor has a common usage mode where physics are not processed (Pause Physics Mode).
I would like to make this kind of usage pattern easier to deal with. The special cases involved with buffered properties, vehicle wheels, bounding boxes and similar things make it a bit unwieldy. One option may be to allow timeScale to smoothly slide all the way down to 0, while still updating the necessary parts of the engine. Right now, setting timeScale to 0 results in a lot of nasty divide-by-zero issues, but there may be a way to work around all of them.
By the way, others making editors found use for the space's forceBufferedStateUpdate and forceWriteBufferFlush methods. These allow buffered entity properties to be used without needing a whole space update.