AndresTraks / BulletSharpPInvoke

.NET wrapper for the Bullet physics library using Platform Invoke

Home Page:http://andrestraks.github.io/BulletSharp/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Adding collision shapes and disposing them

petrasvestartas opened this issue · comments

Hi,

I would like to add collision shapes like this in the constructor. But every time I call dispose method I get memory corrupt exception. I would like to add boxshapes and custom mesh shapes to the same collection: List _collisionShapes = new List(); .

 public sealed class Solver4 : ISimulation, IDisposable {

    //Setup
    public CollisionConfiguration CollisionConfiguration { get; }
    public CollisionDispatcher Dispatcher { get; }
    public BroadphaseInterface Broadphase { get; }
    public DiscreteDynamicsWorld World { get; }


    //Custom objects
    List<CollisionShape> _collisionShapes = new List<CollisionShape>();
    List<Rhino.Geometry.Mesh> _collisionMesh = new List<Rhino.Geometry.Mesh>();
    List<Rhino.Geometry.Transform> _collisionTransform = new List<Rhino.Geometry.Transform>();
    List<float> _collisionMass = new List<float>();

    //Output
    public IList<RigidBody> Bodies = new List<RigidBody>();
    public List<Rhino.Geometry.Mesh> meshesNoTransform = new List<Rhino.Geometry.Mesh>();

    public Solver4() {
        CollisionConfiguration = new DefaultCollisionConfiguration();
        Dispatcher = new CollisionDispatcher(CollisionConfiguration);
        Broadphase = new AxisSweep3_32Bit(new Vector3(-10000, -10000, -10000), new Vector3(10000, 10000, 10000), 1024);
        World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, null, CollisionConfiguration);
        World.Gravity = new Vector3(0, 0, -1.1f);
        GImpactCollisionAlgorithm.RegisterAlgorithm(Dispatcher);
    }

    public Solver4(IRigidBody[] bulletGeometry, List<Rhino.Geometry.Transform> transforms) {

        //Setup
        //Broadphase = new SimpleBroadphase();
        CollisionConfiguration = new DefaultCollisionConfiguration();
        Dispatcher = new CollisionDispatcher(CollisionConfiguration);
        Broadphase = new AxisSweep3_32Bit(new Vector3(-10000, -10000, -10000), new Vector3(10000, 10000, 10000), 1024);
        World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, null, CollisionConfiguration);
        World.Gravity = new Vector3(0,0,-1.1f);
        GImpactCollisionAlgorithm.RegisterAlgorithm(Dispatcher);

        //Add collision Shapes
        if (bulletGeometry.Length > 0 && transforms.Count>0 && bulletGeometry.Length == transforms.Count) {

            int i = 0;
            foreach (var geo in bulletGeometry) {

                switch (geo.id) {
                    case (0):
                    TriangleIndexVertexArray tiva = new TriangleIndexVertexArray(geo.Indices, geo.Vertices);
                    _collisionShapes.Add(CreateGImpactShape(tiva));
                    _collisionMesh.Add(geo.rhinoMesh);
                    _collisionTransform.Add(transforms[i]);
                    _collisionMass.Add(1);//geo.mass
                    tiva.Dispose();
                    break;

                    case (1):
                    _collisionShapes.Add(new BoxShape(geo.X, geo.Y, geo.Z));
                    _collisionMesh.Add(geo.rhinoMesh);
                    _collisionTransform.Add(transforms[i]);
                    _collisionMass.Add(geo.mass);
                    
                    break;
                }
                i++;
            }

            AddCustomObjects();
        }

    }


    public void StepSimulation() {
        World.StepSimulation(1 / 60.0f);
    }

    public void Dispose() {

        this.StandardCleanup();

        if(Bodies.Count>0)
        foreach (var body in Bodies) {
            World.RemoveRigidBody(body);
            body.Dispose();
        }

        if (_collisionShapes.Count > 0) {
            foreach (var a in _collisionShapes) {
                if (a != null)
                    a.Dispose();
            }
        }
    }

    private GImpactMeshShape CreateGImpactShape(TriangleIndexVertexArray shapeData) {
        var shape = new GImpactMeshShape(shapeData);
        shape.Margin = 0;
        shape.UpdateBound();
        return shape;
    }

    private GImpactMeshShape CreateGImpactConvexDecompositionShape(TriangleIndexVertexArray shapeData) {
        //GImpactConvexDecompositionShape shape =
        //    new GImpactConvexDecompositionShape(indexVertexArrays, new Vector3(1), 0.01f);
        //shape.Margin = 0.07f;
        //shape.UpdateBound();
        //return shape;
        throw new NotImplementedException();
    }

    private void AddCustomObjects() {


        if (_collisionMass.Count > 0 ) {

            for (int i = 0; i < _collisionMass.Count; i++) {
                //int id = random.Next(0, 10) % n;
                RhinoApp.WriteLine("s");
                if (_collisionMass[i] < 0.001f) {
                    RigidBody rigidBody = PhysicsHelper.CreateStaticBody(_collisionTransform[i].ToBulletPhysicsTransform(), _collisionShapes[i], World, ref Bodies);
                    rigidBody.CollisionFlags |= CollisionFlags.KinematicObject;
                    rigidBody.ActivationState = ActivationState.DisableDeactivation;
                    meshesNoTransform.Add(_collisionMesh[i]);
                } else {
                    PhysicsHelper.CreateBody(_collisionMass[i], _collisionTransform[i].ToBulletPhysicsTransform(), _collisionShapes[i], World, ref Bodies);//
                    meshesNoTransform.Add(_collisionMesh[i]);
                }


            }
        }


    }


}

I can dispose it like this. But why I cannot do it otherway?

   public sealed class Solver4 : ISimulation, IDisposable {

    //Setup
    public CollisionConfiguration CollisionConfiguration { get; }
    public CollisionDispatcher Dispatcher { get; }
    public BroadphaseInterface Broadphase { get; }
    public DiscreteDynamicsWorld World { get; }

    //Custom objects
    List<TriangleIndexVertexArray> _customShapeData = new List<TriangleIndexVertexArray>();
    List<GImpactMeshShape> _collisionShapes = new List<GImpactMeshShape>();
    List<Rhino.Geometry.Mesh> _collisionMesh = new List<Rhino.Geometry.Mesh>();
    List<Rhino.Geometry.Transform> _collisionTransform = new List<Rhino.Geometry.Transform>();
    List<float> _collisionMass = new List<float>();

    //Output
    public IList<RigidBody> Bodies = new List<RigidBody>();
    public List<Rhino.Geometry.Mesh> meshesNoTransform = new List<Rhino.Geometry.Mesh>();

    public Solver4() {
        CollisionConfiguration = new DefaultCollisionConfiguration();
        Dispatcher = new CollisionDispatcher(CollisionConfiguration);
        Broadphase = new AxisSweep3_32Bit(new Vector3(-10000, -10000, -10000), new Vector3(10000, 10000, 10000), 1024);
        World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, null, CollisionConfiguration);
        World.Gravity = new Vector3(0, 0, -1.1f);
        GImpactCollisionAlgorithm.RegisterAlgorithm(Dispatcher);
    }

    public Solver4(IRigidBody[] bulletGeometry, List<Rhino.Geometry.Transform> transforms) {

        //Setup
        //Broadphase = new SimpleBroadphase();
        CollisionConfiguration = new DefaultCollisionConfiguration();
        Dispatcher = new CollisionDispatcher(CollisionConfiguration);
        Broadphase = new AxisSweep3_32Bit(new Vector3(-10000, -10000, -10000), new Vector3(10000, 10000, 10000), 1024);
        World = new DiscreteDynamicsWorld(Dispatcher, Broadphase, null, CollisionConfiguration);
        World.Gravity = new Vector3(0,0,-1.1f);
        GImpactCollisionAlgorithm.RegisterAlgorithm(Dispatcher);

        //Add collision Shapes
        if (bulletGeometry.Length > 0 && transforms.Count>0 && bulletGeometry.Length == transforms.Count) {

            int i = 0;
            foreach (var geo in bulletGeometry) {

                switch (geo.id) {
                    case (0):

                    _customShapeData.Add( new TriangleIndexVertexArray(geo.Indices, geo.Vertices));                  
                    _collisionShapes.Add(CreateGImpactShape(_customShapeData[i]));
                    _collisionMesh.Add(geo.rhinoMesh);
                    _collisionTransform.Add(transforms[i]);
                    _collisionMass.Add(1);//geo.mass

                    break;

                    case (1):
                    //_collisionShapes.Add(new BoxShape(geo.X, geo.Y, geo.Z));
                    _collisionMesh.Add(geo.rhinoMesh);
                    _collisionTransform.Add(transforms[i]);
                    _collisionMass.Add(geo.mass);
                    
                    break;
                }
                i++;
            }

            AddCustomObjects();
        }

    }



    public void Dispose() {

        this.StandardCleanup();

        if (Bodies.Count > 0) {
            foreach (var body in Bodies) {
                World.RemoveRigidBody(body);
                body.Dispose();
            }
        }

        if (_customShapeData.Count > 0) {
            foreach (var a in _customShapeData) {
                if (a != null)
                    a.Dispose();
            }
        }

        if (_collisionShapes.Count > 0) {
            foreach (var a in _collisionShapes) {
                if (a != null)
                    a.Dispose();
            }
        }
    }



    private void AddCustomObjects() {


        if (_collisionMass.Count > 0 ) {

            for (int i = 0; i < _collisionMass.Count; i++) {
                //int id = random.Next(0, 10) % n;

                if (_collisionMass[i] < 0.001f) {
                    RigidBody rigidBody = PhysicsHelper.CreateStaticBody(_collisionTransform[i].ToBulletPhysicsTransform(), _collisionShapes[i], World, ref Bodies);
                    rigidBody.CollisionFlags |= CollisionFlags.KinematicObject;
                    rigidBody.ActivationState = ActivationState.DisableDeactivation;
                    meshesNoTransform.Add(_collisionMesh[i]);
                } else {
                    PhysicsHelper.CreateBody(_collisionMass[i], _collisionTransform[i].ToBulletPhysicsTransform(), _collisionShapes[i], World, ref Bodies);//
                    meshesNoTransform.Add(_collisionMesh[i]);
                }


            }
        }


    }


    public void StepSimulation() => World.StepSimulation(1 / 60.0f);

    private GImpactMeshShape CreateGImpactShape(TriangleIndexVertexArray shapeData) {
        var shape = new GImpactMeshShape(shapeData);
        shape.Margin = 0;
        shape.UpdateBound();
        return shape;
    }

    private GImpactMeshShape CreateGImpactConvexDecompositionShape(TriangleIndexVertexArray shapeData) {
        throw new NotImplementedException();
    }


}

The GImpactMeshShape will use the TriangleIndexVertexArray, so you can't Dispose the TriangleIndexVertexArray before the GImpactMeshShape like in the first version.

In the second version, the shape data should be disposed after disposing the shapes, even though at that point it doesn't matter much, because the simulation won't be running anymore.

Thank you I corrected the second version it seems more straight forward.