bepuphysics2
bepuphysics2 copied to clipboard
Compisite children with rotation are inactive
when I created composite with children of buch of boxes with indentity rotation everyting is fine. But after I add diffirent rotation to such boxes no rotated boxes are active and dont collide. If there need for demo please say. // Composite rig class
Dictionary<Vector3, (Box, RigidPose, float)> boxes = new Dictionary<Vector3, (Box, RigidPose, float)>();
public void StaticWeld(ShapeType shapeType,Vector3 localPosition,Vector3 localRotation, float mass)
{
if (boxes.ContainsKey(Adapter.Convert(localPosition))) { Debug.WriteLine("is not empty"); return; }
boxes.Add(Adapter.Convert(localPosition),
(new Box(1f,1f,1f), new RigidPose(localPosition/*, new Quaternion(localRotation)*/), mass)); // There is a problem
UpdateComposite();
}
private void UpdateComposite()
{
Vector3 position = Game.physicsSpace.Bodies[bodyHandle].Pose.Position;
Quaternion rotation = Game.physicsSpace.Bodies[bodyHandle].Pose.Orientation;
Vector3 velocity = Game.physicsSpace.Bodies[bodyHandle].Velocity.Linear;
Vector3 angularVelocity = Game.physicsSpace.Bodies[bodyHandle].Velocity.Angular;
Game.physicsSpace.Bodies.Remove(bodyHandle);
Game.physicsSpace.Shapes.Remove(compoundHandle);
CompoundBuilder compoundBuilder = new CompoundBuilder(Game.bufferPool, Game.physicsSpace.Shapes, maxPartLimit);
foreach (var shape in boxes.Values) { compoundBuilder.Add(shape.Item1, shape.Item2, shape.Item3); }
compoundBuilder.BuildDynamicCompound(out Buffer<CompoundChild> children, out BodyInertia bodyInertia, out Vector3 center);
compoundBuilder.Reset();
compoundBuilder.Dispose();
this.compoundHandle = Game.physicsSpace.Shapes.Add(new Compound(children));
this.bodyHandle = Game.physicsSpace.Bodies.Add(
BodyDescription.CreateDynamic(
new RigidPose(position),
bodyInertia,
new CollidableDescription(this.compoundHandle),
new BodyActivityDescription(0.01f)));
Game.physicsSpace.Bodies[bodyHandle].Pose.Orientation = rotation;
Game.physicsSpace.Bodies[bodyHandle].Velocity.Linear = velocity;
Game.physicsSpace.Bodies[bodyHandle].Velocity.Angular = angularVelocity;
WeldRigidBodies();
Awake = true;
}
It's hard to say with certainty what's going on, but:
compoundBuilder.BuildDynamicCompound(out Buffer<CompoundChild> children, out BodyInertia bodyInertia, out Vector3 center);
This outputs a center
which is the computed center of mass for the children that was subtracted from the local pose of all children by the builder. It doesn't appear to be compensated for by adjusting the body's position, so I suspect the body's collider is being shifted around each time a new element is added to the shape.
This should happen regardless of child orientation. I'm not sure what you're observing there; I'll probably need a minimal reproduction in the demos.
And, while it's unrelated to the problem:
- You don't have to remove the body and shape and then re-add them every time. You can get a reference to the shape data through Simulation.Shapes and mutate it.
- Removing the shape does not dispose it by default. For compounds, this means you'll gradually leak memory. If you do remove shapes, consider using Simulation.Shapes.RemoveAndDispose or (Simulation.Shapes.RecursivelyRemoveAndDispose if necessary).
-
Compound
is meant for small numbers of objects and has no acceleration structure. If the compound has a lot of children, consider usingBigCompound
for faster collision testing.
There are example in my project (all flyer parts are boxes but for extendability later want to add other shapes, All boxes (transparents and solids) works correctly, but engines(rotated boxes) don't react to static terrain)
- You are right about body center stuff, but it rotation is still (even if just for me) bugged.
- I can't find where I can find reference to shape, because shape needs shape id instead of shapeHandle and I cant find class such as ShapeReferences or such.
- Also thanks for warning that Shape needs to be disposed and that remove doesn't cut it.
- Also there is confusion of how we can define Big or Small Compond, like big is like 200 and small 20 or (big)20:(small)5. (I use simple compound for testing purposes for now so later replace it to bigCompound.)
Anyways now I will try replicate it on demo and see if it's my oversight.
I can't find where I can find reference to shape, because shape needs shape id instead of shapeHandle and I cant find class such as ShapeReferences or such.
Unlike bodies and constraints, shape allocations in the engine do not move and so don't have a handle based indirection. You can get direct memory references/pointers safely:
var sphereShape = new Sphere(3);
var sphereIndex = Simulation.Shapes.Add(sphereShape);
ref Sphere sphereShapeReference = ref Simulation.Shapes.GetShape<Sphere>(sphereIndex.Index);
Simulation.Shapes[sphereIndex.Type].GetShapeData(sphereIndex.Index, out var sphereShapePointer, out var sphereShapeSizeInBytes);
Also there is confusion of how we can define Big or Small Compond, like big is like 200 and small 20 or (big)20:(small)5. (I use simple compound for testing purposes for now so later replace it to bigCompound.)
There's no fixed answer based on count- the types of shapes and how they are positioned in the compound matter too. Usually a small Compound
should be on the order of 1-5 convex shapes, maybe a bit more if the shapes are super cheap like spheres. If there's something about the compound such that you know an acceleration structure just isn't going to do much and almost all children are going to be tested regardless, then using a Compound
with larger counts could still make sense.
The only difference between the two is the presence of an acceleration structure in BigCompound
, so the most correct answer is "use BigCompound
if an acceleration structure is a net win for performance."