Page 1 of 1

Add PreConfigured RigidBody To GameObject (Unity3D)

Posted: Fri Apr 03, 2020 12:50 pm
by EliasNemer
Hello,

in my Billiard Game i have a script which does an offline simulation so that i may predict trajectory. it is very similar to the script that comes with BulletUnity Library called OfflineBallSimulation..

in this script the code takes all collision objects in the world, creates copies of the rigidBodies and adds them to an offline World and simulates there.

I would like to add collision callback to the simulation so that i may also get the collision that may first occur in the simualtion. this is difficult because if i want to add the BCollisionCallbackDefaults script i would need a gameObject to add it to. but i cannot add the Created rigidbody to a gameObject due to serialization or something of the sort. it is a difficult task.

so i am asking if there is someway i have not seen which would make this easier..

here is some of my code

Code: Select all

void Simulate()
    {
        if (!simulationStarted)
        {
            if (!createdWorld && ballInstantiator.getBallsLoaded())
            {
                int j = 0;
                //This should create a copy of the BPhysicsWorld with the same settings
                BPhysicsWorld bw = BPhysicsWorld.Get();
                bw.CreatePhysicsWorld(out cw, out CollisionConf, out Dispatcher, out Broadphase, out Solver, out softBodyWorldInfo);
                World = (DiscreteDynamicsWorld)cw;

                //Copy all existing rigidbodies in scene
                // IMPORTANT rigidbodies must be added to the offline world in the same order that they are in the source world
                // this is because collisions must be resolved in the same order for the sim to be deterministic
                DiscreteDynamicsWorld sourceWorld = (DiscreteDynamicsWorld)bw.world;

                BulletSharp.Math.Matrix mm = BulletSharp.Math.Matrix.Identity;
                for (int i = 0; i < sourceWorld.NumCollisionObjects; i++)
                {
                    //here we add the RigidBodies from the source World
                    CollisionObject co = sourceWorld.CollisionObjectArray[i];

                    if (co != null && co.UserObject is BRigidBody)
                    {
                        BRigidBody rb = (BRigidBody)co.UserObject;
                        float mass = rb.isDynamic() ? rb.mass : 0f;
                        BCollisionShape existingShape = rb.GetComponent<BCollisionShape>();
                        CollisionShape shape = null;
                        if (existingShape is BSphereShape)
                        {
                            shape = ((BSphereShape)existingShape).CopyCollisionShape();
                            // this might need to be put later after rigidbpdy is created
                            //initialBallPositions[j] = rb.RigidBody.WorldTransform.Origin;
                            //updatedInitialPositions = true;

                            print(rb.name);
                        }
                        else if (existingShape is BBoxShape)
                        {
                            shape = ((BBoxShape)existingShape).CopyCollisionShape();
                        }
                        else if (existingShape is BConvexHullShape)
                        {
                            shape = ((BConvexHullShape)existingShape).CopyCollisionShape();
                        }

                        RigidBody bulletRB = null;
                        BulletSharp.Math.Vector3 localInertia = new BulletSharp.Math.Vector3();
                        rb.CreateOrConfigureRigidBody(ref bulletRB, ref localInertia, shape, null);
                        BulletSharp.Math.Vector3 pos = rb.GetCollisionObject().WorldTransform.Origin;
                        BulletSharp.Math.Quaternion rot = rb.GetCollisionObject().WorldTransform.GetOrientation();
                        BulletSharp.Math.Matrix.AffineTransformation(1f, ref rot, ref pos, out mm);
                        bulletRB.WorldTransform = mm;
                        World.AddRigidBody(bulletRB, rb.groupsIBelongTo, rb.collisionMask);

                        if (existingShape is BSphereShape)
                        {
                            for(int k = 0; k <= 15; k++)
                            {
                                if (bulletRB.WorldTransform.Origin.ToUnity() == ballRB[k].transform.position)
                                {
                                    hiddenBall[k] = bulletRB;
                                    
                                    print(ballRB[k].gameObject.name);
                                    print(k);
                                }
                            }
                            
                            j++;
                            
                        }
                        if (rb == ballRB[0])
                        {
                            print("This is CueBall RB: " + rb.gameObject.name);
                            bulletBallRb[0] = bulletRB;
                            initialBallPositions[0] = rb.RigidBody.WorldTransform.Origin;
                            //bCollisionCallBack[0] = bulletRB.;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[1])
                        {
                            bulletBallRb[1] = bulletRB;
                            initialBallPositions[1] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[2])
                        {
                            bulletBallRb[2] = bulletRB;
                            initialBallPositions[2] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[3])
                        {
                            bulletBallRb[3] = bulletRB;
                            initialBallPositions[3] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[4])
                        {
                            bulletBallRb[4] = bulletRB;
                            initialBallPositions[4] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[5])
                        {
                            bulletBallRb[5] = bulletRB;
                            initialBallPositions[5] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[6])
                        {
                            bulletBallRb[6] = bulletRB;
                            initialBallPositions[6] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[7])
                        {
                            bulletBallRb[7] = bulletRB;
                            initialBallPositions[7] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[8])
                        {
                            bulletBallRb[8] = bulletRB;
                            initialBallPositions[8] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[9])
                        {
                            bulletBallRb[9] = bulletRB;
                            initialBallPositions[9] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[10])
                        {
                            bulletBallRb[10] = bulletRB;
                            initialBallPositions[10] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[11])
                        {
                            bulletBallRb[11] = bulletRB;
                            initialBallPositions[11] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[12])
                        {
                            bulletBallRb[12] = bulletRB;
                            initialBallPositions[12] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[13])
                        {
                            bulletBallRb[13] = bulletRB;
                            initialBallPositions[13] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[14])
                        {
                            bulletBallRb[14] = bulletRB;
                            initialBallPositions[14] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                        if (rb == ballRB[15])
                        {
                            bulletBallRb[15] = bulletRB;
                            initialBallPositions[15] = rb.RigidBody.WorldTransform.Origin;
                            //print("Ball Rb Name: " + ballRb.name);
                        }
                    }
                }
                updatedInitialPositions = true;
                createdWorld = true;
                print("World Created");
            }

            simulationStarted = true;

            for (int i = 0; i < numberOfSimulationSteps; i++)
            {
                if (i == 1)
                    bulletBallRb[0].ApplyImpulse(force.ToBullet(), positionToHit.ToBullet());

                int numSteps = World.StepSimulation(1 / 100f, 10, 1f / 100f);
                ballPositionsOfflineSim[i] = bulletBallRb[0].WorldTransform.Origin.ToUnity();

                if (bCollisionCallBack[0].getObjectBallHit() == "9BallObject (BulletUnity.BRigidBody)")
                {
                    ballPositionsHitOfflineSim[i] = bulletBallRb[9].WorldTransform.Origin.ToUnity();
                    print("goig to hit 9 ball");
                }

                if(bCollisionCallBack[0].getHitBall() > 0)
                {
                    print("Simulation: ball hit");
                }



                //FirstBallPositionsOfflineSim[i] = 
            }

            for (int j = 0; j <= 15; j++)
            {
                hiddenBall[j].AngularVelocity *= 0;
                hiddenBall[j].LinearVelocity *= 0;
                hiddenBall[j].Translate(-(hiddenBall[j].WorldTransform.Origin - initialBallPositions[j]));
                //print("Original Position: " + initialBallPositions[j] + "; Current Position: " + hiddenBall[j].WorldTransform.Origin + "; Velocity: " + hiddenBall[j].velocity + "; Angular Velocity: " + hiddenBall[j].angularVelocity);
            }
            lineRenderer[0].SetPositions(ballPositionsOfflineSim.ToArray());
            lineRenderer[9].SetPositions(ballPositionsHitOfflineSim.ToArray());
        }
    }



Re: Add PreConfigured RigidBody To GameObject (Unity3D)

Posted: Sun Apr 05, 2020 8:38 pm
by EliasNemer
i found a solution to this issue, where i can use the function CheakCollidedWith()

this fixes my issue, but now i have another issue, where CheakCollidedWith() allways returns true no matter what.

here is my code

Code: Select all

void Simulate()
    {
        if (!simulationStarted)
        {
            if (!createdWorld && ballInstantiator.getBallsLoaded())
            {
                int j = 0;
                //This should create a copy of the BPhysicsWorld with the same settings
                BPhysicsWorld bw = BPhysicsWorld.Get();
                bw.CreatePhysicsWorld(out cw, out CollisionConf, out Dispatcher, out Broadphase, out Solver, out softBodyWorldInfo);
                World = (DiscreteDynamicsWorld)cw;

                //Copy all existing rigidbodies in scene
                // IMPORTANT rigidbodies must be added to the offline world in the same order that they are in the source world
                // this is because collisions must be resolved in the same order for the sim to be deterministic
                DiscreteDynamicsWorld sourceWorld = (DiscreteDynamicsWorld)bw.world;

                BulletSharp.Math.Matrix mm = BulletSharp.Math.Matrix.Identity;
                for (int i = 0; i < sourceWorld.NumCollisionObjects; i++)
                {
                    
                    //here we add the RigidBodies from the source World
                    CollisionObject co = sourceWorld.CollisionObjectArray[i];

                    if (co != null && co.UserObject is BRigidBody)
                    {
                        BRigidBody rb = (BRigidBody)co.UserObject;
                        float mass = rb.isDynamic() ? rb.mass : 0f;
                        BCollisionShape existingShape = rb.GetComponent<BCollisionShape>();
                        CollisionShape shape = null;
                        if (existingShape is BSphereShape)
                        {
                            shape = ((BSphereShape)existingShape).CopyCollisionShape();
                        }
                        else if (existingShape is BBoxShape)
                        {
                            shape = ((BBoxShape)existingShape).CopyCollisionShape();
                        }
                        else if (existingShape is BConvexHullShape)
                        {
                            shape = ((BConvexHullShape)existingShape).CopyCollisionShape();
                        }

                        RigidBody bulletRB = null;
                        BulletSharp.Math.Vector3 localInertia = new BulletSharp.Math.Vector3();
                        rb.CreateOrConfigureRigidBody(ref bulletRB, ref localInertia, shape, null);
                        BulletSharp.Math.Vector3 pos = rb.GetCollisionObject().WorldTransform.Origin;
                        
                        BulletSharp.Math.Quaternion rot = rb.GetCollisionObject().WorldTransform.GetOrientation();
                        BulletSharp.Math.Matrix.AffineTransformation(1f, ref rot, ref pos, out mm);
                        bulletRB.WorldTransform = mm;
                        World.AddRigidBody(bulletRB, rb.groupsIBelongTo, rb.collisionMask);

                        if (existingShape is BSphereShape)
                        {
                            for(int k = 0; k <= 15; k++)
                            {
                                if (bulletRB.WorldTransform.Origin.ToUnity() == ballRB[k].transform.position)
                                {
                                    hiddenBall[k] = bulletRB;
                                    
                                }
                            }
                            j++;
                        }
                        if (rb == ballRB[0])
                        {
                            print("This is CueBall RB: " + rb.gameObject.name);
                            bulletBallRb[0] = bulletRB;
                            initialBallPositions[0] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[0] = bulletRB;

                        }
                        if (rb == ballRB[1])
                        {
                            bulletBallRb[1] = bulletRB;
                            initialBallPositions[1] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[1] = bulletRB;
                        }
                        if (rb == ballRB[2])
                        {
                            bulletBallRb[2] = bulletRB;
                            initialBallPositions[2] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[2] = bulletRB;
                        }
                        if (rb == ballRB[3])
                        {
                            bulletBallRb[3] = bulletRB;
                            initialBallPositions[3] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[3] = bulletRB;
                        }
                        if (rb == ballRB[4])
                        {
                            bulletBallRb[4] = bulletRB;
                            initialBallPositions[4] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[4] = bulletRB;
                        }
                        if (rb == ballRB[5])
                        {
                            bulletBallRb[5] = bulletRB;
                            initialBallPositions[5] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[5] = bulletRB;
                        }
                        if (rb == ballRB[6])
                        {
                            bulletBallRb[6] = bulletRB;
                            initialBallPositions[6] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[6] = bulletRB;
                        }
                        if (rb == ballRB[7])
                        {
                            bulletBallRb[7] = bulletRB;
                            initialBallPositions[7] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[7] = bulletRB;

                        }
                        if (rb == ballRB[8])
                        {
                            bulletBallRb[8] = bulletRB;
                            initialBallPositions[8] = rb.RigidBody.WorldTransform.Origin;
                            collisionObject[8] = bulletRB;
                        }
                        if (rb == ballRB[9])
                        {
                            bulletBallRb[9] = bulletRB;
                            initialBallPositions[9] = rb.RigidBody.WorldTransform.Origin;
                        }
                        if (rb == ballRB[10])
                        {
                            bulletBallRb[10] = bulletRB;
                            initialBallPositions[10] = rb.RigidBody.WorldTransform.Origin;
                    
                        }
                        if (rb == ballRB[11])
                        {
                            bulletBallRb[11] = bulletRB;
                            initialBallPositions[11] = rb.RigidBody.WorldTransform.Origin;
                        }
                        if (rb == ballRB[12])
                        {
                            bulletBallRb[12] = bulletRB;
                            initialBallPositions[12] = rb.RigidBody.WorldTransform.Origin;
                        }
                        if (rb == ballRB[13])
                        {
                            bulletBallRb[13] = bulletRB;
                            initialBallPositions[13] = rb.RigidBody.WorldTransform.Origin;
                        }
                        if (rb == ballRB[14])
                        {
                            bulletBallRb[14] = bulletRB;
                            initialBallPositions[14] = rb.RigidBody.WorldTransform.Origin;
                        }
                        if (rb == ballRB[15])
                        {
                            bulletBallRb[15] = bulletRB;
                            initialBallPositions[15] = rb.RigidBody.WorldTransform.Origin;
                        }
                    }
                }
                updatedInitialPositions = true;
                createdWorld = true;
                print("World Created");
            }

            simulationStarted = true;
            int a = 0;
            for (int i = 0; i < numberOfSimulationSteps; i++)
            {
                if (i == 1)
                    bulletBallRb[0].ApplyImpulse(force.ToBullet(), positionToHit.ToBullet());

                int numSteps = World.StepSimulation(1 / 100f, 10, 1f / 100f);
                ballPositionsOfflineSim[i] = bulletBallRb[0].WorldTransform.Origin.ToUnity();
                print("ball Hit: " + bulletBallRb[0].CheckCollideWith(bulletBallRb[1]));
                if(!gotFirstBallHit)
                {
                    if (bulletBallRb[0].CheckCollideWith(collisionObject[1]))
                    {
                        collisionDetected[1] = true;
                        a = i;
                        gotFirstBallHit = true;
                    }
                    if (bulletBallRb[0].CheckCollideWith(collisionObject[2]))
                    {
                        collisionDetected[2] = true;
                        a = i;
                        gotFirstBallHit = true;
                    }
                    if (bulletBallRb[0].CheckCollideWith(collisionObject[3]))
                    {
                        collisionDetected[3] = true;
                        a = i;
                        gotFirstBallHit = true;
                    }
                    if (bulletBallRb[0].CheckCollideWith(collisionObject[4]))
                    {
                        collisionDetected[4] = true;
                        a = i;
                        gotFirstBallHit = true;
                    }
                    if (bulletBallRb[0].CheckCollideWith(collisionObject[5]))
                    {
                        collisionDetected[5] = true;
                        a = i;
                        gotFirstBallHit = true;
                    }
                    if (bulletBallRb[0].CheckCollideWith(collisionObject[6]))
                    {
                        collisionDetected[6] = true;
                        a = i;
                        gotFirstBallHit = true;
                    }
                    if (bulletBallRb[0].CheckCollideWith(collisionObject[7]))
                    {
                        collisionDetected[7] = true;
                        a = i;
                        gotFirstBallHit = true;
                    }
                    if (bulletBallRb[0].CheckCollideWith(collisionObject[8]))
                    {
                        collisionDetected[8] = true;
                        a = i;
                        gotFirstBallHit = true;
                    }
                }

                if(collisionDetected[1])
                    ballPositionsHitOfflineSim[i - a] = bulletBallRb[1].WorldTransform.Origin.ToUnity();
                if (collisionDetected[2])
                    ballPositionsHitOfflineSim[i - a] = bulletBallRb[2].WorldTransform.Origin.ToUnity();
                if (collisionDetected[3])
                    ballPositionsHitOfflineSim[i - a] = bulletBallRb[3].WorldTransform.Origin.ToUnity();
                if (collisionDetected[4])
                    ballPositionsHitOfflineSim[i - a] = bulletBallRb[4].WorldTransform.Origin.ToUnity();
                if (collisionDetected[5])
                    ballPositionsHitOfflineSim[i - a] = bulletBallRb[5].WorldTransform.Origin.ToUnity();
                if (collisionDetected[6])
                    ballPositionsHitOfflineSim[i - a] = bulletBallRb[6].WorldTransform.Origin.ToUnity();
                if (collisionDetected[7])
                    ballPositionsHitOfflineSim[i - a] = bulletBallRb[7].WorldTransform.Origin.ToUnity();
                if (collisionDetected[8])
                    ballPositionsHitOfflineSim[i - a] = bulletBallRb[8].WorldTransform.Origin.ToUnity();

                print("1Ball Collision: " + collisionDetected[1]);
                print("2Ball Collision: " + collisionDetected[2]);
                print("3Ball Collision: " + collisionDetected[3]);
                print("4Ball Collision: " + collisionDetected[4]);
                print("5Ball Collision: " + collisionDetected[5]);
                print("6Ball Collision: " + collisionDetected[6]);
                print("7Ball Collision: " + collisionDetected[7]);
                print("8Ball Collision: " + collisionDetected[8]);
                // all of these print true for some reason
                
            }

            lineRenderer[0].SetPositions(ballPositionsOfflineSim.ToArray());

            for(int k = 0; k <= 15; k++)
            {
                if(collisionDetected[k])
                    lineRenderer[k].SetPositions(ballPositionsHitOfflineSim.ToArray());
            }
           // lineRenderer[9].SetPositions(ballPositionsHitOfflineSim.ToArray());

            for (int j = 0; j <= 15; j++)
            {
                hiddenBall[j].AngularVelocity *= 0;
                hiddenBall[j].LinearVelocity *= 0;
                hiddenBall[j].Translate(-(hiddenBall[j].WorldTransform.Origin - initialBallPositions[j]));
                collisionDetected[j] = false;
                //print("Original Position: " + initialBallPositions[j] + "; Current Position: " + hiddenBall[j].WorldTransform.Origin + "; Velocity: " + hiddenBall[j].velocity + "; Angular Velocity: " + hiddenBall[j].angularVelocity);
            }

            gotFirstBallHit = false;
        }
    }
can anyone point out why this might happen?
from my code it doesnt seem it should happen..

Re: Add PreConfigured RigidBody To GameObject (Unity3D)

Posted: Mon Apr 06, 2020 4:20 pm
by EliasNemer
CheakCollidedWith() allways return true, since it only references if the objects are allowed to collide, thus obviously they will return true,

but i still need an answer to my issue of collision detection in the simulation..

i found this code:

Code: Select all

btCollisionAlgorithm* pAlgorithm = pBtWorld->getDispatcher()->findAlgorithm( pBulletObj1, pBulletObj2 );
btManifoldResult oManifoldResult( pBulletObj1, pBulletObj2 );
pAlgorithm->processCollision( pBulletObj1, pBulletObj2, pBtWorld->getDispatchInfo(), &oManifoldResult );
btPersistentManifold* pManifold = oManifoldResult.getPersistentManifold();
in the thread at this URL: viewtopic.php?f=9&t=3188

this is written in c++

i need it in c# so i am trying to change it..

till now i have the following:

Code: Select all

CollisionAlgorithm pAlgorithm = World.Dispatcher.FindAlgorithm(collisionObject[0], collisionObject[b]); 
ManifoldResult manifoldResult(pBulletObj1, pBulletObj2);
pAlgorithm.ProcessCollision(pBulletObj1, pBulletObj2, World.DispatchInfo, &manifoldResult);
PersistentManifold pManifold = oManifoldResult.getPersistentManifold();
but i am getting error throughout..

the first error is that FindAlgorith takes collisionObjectWrapper not CollisionObject,
so my question is how do i reference CollisionObjectWrapper. i cannot find it. for example i cannot do:

CollisionObjectWrapper cow = sourceWorld.CollisionObjectArray.getCollisionObjectWrapper();
what is a collisionObjectWrapper and how do i reference it?

secondly, ManifoldResult manifoldResult(pBulletObj1, pBulletObj2); is giving me an error.
Error CS8112 'manifoldResult(CollisionObjectWrapper, CollisionObjectWrapper)' is a local function and must therefore always have a body.

is this an example of type and Variable name?


any help would be appreciated..

Re: Add PreConfigured RigidBody To GameObject (Unity3D)

Posted: Wed Apr 08, 2020 9:01 am
by anthrax11
This page describes a few ways to implement collision callbacks:
https://github.com/AndresTraks/BulletSh ... d-Triggers

Re: Add PreConfigured RigidBody To GameObject (Unity3D)

Posted: Wed Apr 08, 2020 6:20 pm
by EliasNemer
thank you for your reply,

very intresting and usefull.. i have a few questions though..

1) is ghostObject a special object or it a regular object assigned to collisionObject variable ghostObject..

2) if i want to find only collisions between the cueBall-ball collisions only an not go through cueball-table collisions, how would i seperate in the pairArray?

thank you,