Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compisite children with rotation are inactive #244

Open
Paulius0706 opened this issue Nov 20, 2022 · 3 comments
Open

Compisite children with rotation are inactive #244

Paulius0706 opened this issue Nov 20, 2022 · 3 comments

Comments

@Paulius0706
Copy link

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;
            }
@RossNordby
Copy link
Member

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:

  1. 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.
  2. 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).
  3. Compound is meant for small numbers of objects and has no acceleration structure. If the compound has a lot of children, consider using BigCompound for faster collision testing.

@Paulius0706
Copy link
Author

Paulius0706 commented Nov 21, 2022

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)
paveikslas

  1. You are right about body center stuff, but it rotation is still (even if just for me) bugged.
  2. 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.
  3. Also thanks for warning that Shape needs to be disposed and that remove doesn't cut it.
  4. 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.

@RossNordby
Copy link
Member

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."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants