public void BuildCollisionData(Color[] map, int width, int height, Vector3 bottomLeft) { Vector2 dim = Vector2.One; Vector3 scale = new Vector3(dim, 1); BoxShape collisionBoxShape = new BoxShape(new IndexedVector3(0.5f)); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { int currentIndex = x + y * width; if (map[currentIndex] == Color.White) { float yOffset = -dim.Y;//0f;// -(dim.Y / 2f); Vector3 position = new Vector3(x - bottomLeft.X, (bottomLeft.Y - y) + yOffset, bottomLeft.Z); m_waterLocations.Add(position); } if (map[currentIndex] == Color.White) { // check the 4 ordinals , if we're surrounded by other solid blocks // then we don't need a block here. bool upSet = false; bool downSet = false; bool leftSet = false; bool rightSet = false; if (x >= 1 && x < width - 1) { if (map[currentIndex - 1] == Color.White) { leftSet = true; } if (map[currentIndex + 1] == Color.White) { rightSet = true; } } if (y >= 1 && y < height - 1) { if (map[currentIndex - height] == Color.White) { upSet = true; } if (map[currentIndex + height] == Color.White) { downSet = true; } } // if we're not surrounded by blocks then add in. if (!(upSet && downSet && leftSet && rightSet)) { Object rigifdBody; float yOffset = -dim.Y;//0f;// -(dim.Y / 2f); Vector3 position = new Vector3(x - bottomLeft.X, (bottomLeft.Y - y) + yOffset, bottomLeft.Z); RigidBodyConstructionInfo constructionInfo = new BulletXNA.BulletDynamics.RigidBodyConstructionInfo(0f, null, (BulletXNA.BulletCollision.CollisionShape)collisionBoxShape); RigidBody rigidBody = new BulletXNA.BulletDynamics.RigidBody(constructionInfo); Matrix bsm = Matrix.CreateTranslation(position); rigidBody.SetWorldTransform(bsm); // FIXME MAN - setup some collision flags on these bodies... BulletXNA.BulletCollision.CollisionFilterGroups flags = (BulletXNA.BulletCollision.CollisionFilterGroups)(1 << 8); BulletXNA.BulletCollision.CollisionFilterGroups mask = (BulletXNA.BulletCollision.CollisionFilterGroups)(1 << 9); //rigidBody.CollisionFlags |= (BulletSharp.CollisionFlags)CollisionObjectType.Ground; m_dynamicsWorld.AddRigidBody(rigidBody, flags, mask); } } // Build water ghost objects. foreach (Vector3 pos in m_waterLocations) { GhostObject ghostObject = new GhostObject(); ghostObject.SetCollisionShape((BulletXNA.BulletCollision.CollisionShape)collisionBoxShape); CollisionFilterGroups flags = (CollisionFilterGroups)(1 << 10); CollisionFilterGroups mask = (CollisionFilterGroups)(1 << 9); ghostObject.SetCollisionFlags(CollisionFlags.CF_NO_CONTACT_RESPONSE | CollisionFlags.CF_STATIC_OBJECT); // We can choose to make it "solid" if we want... ghostObject.SetWorldTransform(BulletXNA.LinearMath.IndexedMatrix.CreateTranslation(pos)); m_dynamicsWorld.AddCollisionObject(ghostObject, flags, mask); break; } } } }
protected override void Initialize() { base.Initialize(); SetCameraDistance(50.0f); ///collision configuration contains default setup for memory, collision setup m_collisionConfiguration = new DefaultCollisionConfiguration(); //m_collisionConfiguration.setConvexConvexMultipointIterations(); ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new CollisionDispatcher(m_collisionConfiguration); m_broadphase = new DbvtBroadphase(); ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) m_constraintSolver = new SequentialImpulseConstraintSolver(); m_dynamicsWorld = new DiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_constraintSolver, m_collisionConfiguration); IndexedVector3 gravity = new IndexedVector3(0, -10, 0); m_dynamicsWorld.SetGravity(ref gravity); // NEW => btGhostPairCallback ================================= m_ghostPairCallback = new GhostPairCallback(); m_dynamicsWorld.GetBroadphase().GetOverlappingPairCache().SetInternalGhostPairCallback(m_ghostPairCallback); // Needed once to enable ghost objects inside Bullet // NEW => btGhostObject ======================================= m_ghostObject = new GhostObject(); CollisionShape shape = new BoxShape(new IndexedVector3(5f)); // As far as I know only the world aabb of the shape will be used (i.e. a box always parallel to the x,y,z axis of variable size) m_collisionShapes.Add(shape); m_ghostObject.SetCollisionShape(shape); m_ghostObject.SetCollisionFlags(CollisionFlags.CF_NO_CONTACT_RESPONSE); // We can choose to make it "solid" if we want... m_dynamicsWorld.AddCollisionObject(m_ghostObject, CollisionFilterGroups.SensorTrigger, CollisionFilterGroups.AllFilter & ~CollisionFilterGroups.SensorTrigger); //m_ghostObject.setWorldTransform(btTransform(btQuaternion::getIdentity(),btVector3(0,5,-15))); IndexedMatrix im = IndexedMatrix.CreateFromQuaternion(quatDeg45Y); im._origin = new IndexedVector3(0, 5, -15); m_ghostObject.SetWorldTransform(im); // NEW => btPairCachingGhostObject ============================ m_pairCachingGhostObject = new PairCachingGhostObject(); shape = new ConeShape(7.0f, 14.0f); m_collisionShapes.Add(shape); m_pairCachingGhostObject.SetCollisionShape(shape); m_pairCachingGhostObject.SetCollisionFlags(CollisionFlags.CF_NO_CONTACT_RESPONSE); // We can choose to make it "solid" if we want... m_dynamicsWorld.AddCollisionObject(m_pairCachingGhostObject, CollisionFilterGroups.SensorTrigger, CollisionFilterGroups.AllFilter & ~CollisionFilterGroups.SensorTrigger); //m_pairCachingGhostObject.setWorldTransform(btTransform(btQuaternion::getIdentity(),btVector3(0,5,15))); im._origin = new IndexedVector3(0, 7, 15); m_pairCachingGhostObject.SetWorldTransform(im); //============================================================= ///create a few basic rigid bodies CollisionShape groundShape = new BoxShape(new IndexedVector3(50)); m_collisionShapes.Add(groundShape); IndexedMatrix groundTransform = IndexedMatrix.Identity; groundTransform._origin = new IndexedVector3(0, -50, 0); float mass = 0.0f; LocalCreateRigidBody(mass, groundTransform, groundShape); // spawn some cubes (code pasted from appBasicDemo...) if (true) { //create a few dynamic rigidbodies CollisionShape colShape = new BoxShape(new IndexedVector3(SCALING, SCALING, SCALING)); //btCollisionShape* colShape = new btSphereShape(btScalar(1.)); //CollisionShape colShape = new CylinderShape(new IndexedVector3(1f, 1, 1f)); m_collisionShapes.Add(colShape); /// Create Dynamic Objects IndexedMatrix startTransform = IndexedMatrix.Identity; mass = 1f; //rigidbody is dynamic if and only if mass is non zero, otherwise static bool isDynamic = mass != 0f; IndexedVector3 localInertia = IndexedVector3.Zero; if (isDynamic) { colShape.CalculateLocalInertia(mass, out localInertia); } float start_x = START_POS_X - ARRAY_SIZE_X / 2; float start_y = START_POS_Y; float start_z = START_POS_Z - ARRAY_SIZE_Z / 2; for (int k = 0; k < ARRAY_SIZE_Y; k++) { for (int i = 0; i < ARRAY_SIZE_X; i++) { for (int j = 0; j < ARRAY_SIZE_Z; j++) { startTransform._origin = (new IndexedVector3(2.0f * i + start_x, 20 + 2.0f * k + start_y, 2.0f * j + start_z) * SCALING); //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects DefaultMotionState myMotionState = new DefaultMotionState(startTransform, IndexedMatrix.Identity); RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, colShape, localInertia); RigidBody body = new RigidBody(rbInfo); //body.setContactProcessingThreshold(colShape.getContactBreakingThreshold()); body.SetActivationState(ActivationState.ISLAND_SLEEPING); m_dynamicsWorld.AddRigidBody(body); body.SetActivationState(ActivationState.ISLAND_SLEEPING); body.SetUserPointer(String.Format("Box X{0} Y{1} Z{2}", k, i, j)); } } } } ClientResetScene(); }