/// <summary> /// Initialize physical-engine related stuff and set callbacks to respond to contact start / ended / processed events. /// </summary> public static void Initialize() { // set collision start callback BulletSharp.ManifoldPoint.ContactAdded += ( BulletSharp.ManifoldPoint cp, BulletSharp.CollisionObjectWrapper obj0, int partId0, int index0, BulletSharp.CollisionObjectWrapper obj1, int partId1, int index1) => { // get physical bodies BasicPhysicalBody body0 = obj0.CollisionObject.UserObject as BasicPhysicalBody; BasicPhysicalBody body1 = obj1.CollisionObject.UserObject as BasicPhysicalBody; // if one of the bodies don't support collision skip if (body0 == null || body1 == null) { return; } // store both bodies for the collision end event cp.UserPersistentData = new CollisionPersistData(body0, body1); // send collision events CollisionData data = new CollisionData(ToMonoGame.Vector(cp.PositionWorldOnA)); body0.CallCollisionStart(body1, ref data); body1.CallCollisionStart(body0, ref data); }; // set while-collising callback BulletSharp.PersistentManifold.ContactProcessed += ( BulletSharp.ManifoldPoint cp, BulletSharp.CollisionObject body0, BulletSharp.CollisionObject body1) => { if (cp.UserPersistentData == null) { return; } CollisionPersistData data = (CollisionPersistData)cp.UserPersistentData; data.Body0.CallCollisionProcess(data.Body1); data.Body1.CallCollisionProcess(data.Body0); }; // set collising-ended callback BulletSharp.PersistentManifold.ContactDestroyed += (object userPersistantData) => { if (userPersistantData == null) { return; } CollisionPersistData data = (CollisionPersistData)userPersistantData; data.Body0.CallCollisionEnd(data.Body1); data.Body1.CallCollisionEnd(data.Body0); }; }
/// <summary> /// Convert an array of vectors from Bullet3d to MonoGame. /// </summary> /// <param name="bvecs">Bullet3d vectors array to convert.</param> /// <returns>Array of MonoGame vectors.</returns> public static Vector3[] Vectors(BulletSharp.Math.Vector3[] bvecs) { Vector3[] vectors = new Vector3[bvecs.Length]; int i = 0; foreach (var bvector in bvecs) { vectors[i++] = ToMonoGame.Vector(bvector); } return(vectors); }
/// <summary> /// Draw a line with a single color. /// </summary> /// <param name="from">Starting pos.</param> /// <param name="to">Ending pos.</param> /// <param name="color">Color.</param> public override void DrawLine(ref BulletSharp.Math.Vector3 from, ref BulletSharp.Math.Vector3 to, ref BulletSharp.Math.Vector3 color) { Color col = new Color(color.X, color.Y, color.Z); var vertices = new[] { new VertexPositionColor(ToMonoGame.Vector(from), col), new VertexPositionColor(ToMonoGame.Vector(to), col) }; _device.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 1); }
/// <summary> /// Perform a raycast test and return colliding results, using native bullet objects. /// </summary> /// <param name="bStart">Start ray vector (bullet vector).</param> /// <param name="bEnd">End ray vector (bullet vector).</param> /// <param name="resultsCallback">BulletSharp results callback.</param> internal RaycastResults Raycast(BulletSharp.Math.Vector3 bStart, BulletSharp.Math.Vector3 bEnd, BulletSharp.RayResultCallback resultsCallback) { // perform the ray test _world.RayTestRef(ref bStart, ref bEnd, resultsCallback); // create results object to return RaycastResults results = new RaycastResults(); // parse data based on type // closest result / closest but not me types: if (resultsCallback is BulletSharp.ClosestRayResultCallback) { // convert to closest results type BulletSharp.ClosestRayResultCallback closestReults = resultsCallback as BulletSharp.ClosestRayResultCallback; // set results data results.HasHit = closestReults.HasHit; if (results.HasHit) { results.Collisions = new RaycastResults.SingleResult[1]; results.Collisions[0].HitFraction = closestReults.ClosestHitFraction; results.Collisions[0].CollisionNormal = ToMonoGame.Vector(closestReults.HitNormalWorld); results.Collisions[0].CollisionPoint = ToMonoGame.Vector(closestReults.HitPointWorld); results.Collisions[0].CollisionBody = (closestReults.CollisionObject.UserObject as BasicPhysicalBody).EcsComponent; } } // all results type else if (resultsCallback is BulletSharp.AllHitsRayResultCallback) { // convert to all results type BulletSharp.AllHitsRayResultCallback allResults = resultsCallback as BulletSharp.AllHitsRayResultCallback; // set results data results.HasHit = allResults.HasHit; if (results.HasHit) { results.Collisions = new RaycastResults.SingleResult[allResults.CollisionObjects.Count]; for (int i = 0; i < allResults.CollisionObjects.Count; ++i) { results.Collisions[i].HitFraction = allResults.HitFractions[i]; results.Collisions[i].CollisionNormal = ToMonoGame.Vector(allResults.HitNormalWorld[i]); results.Collisions[i].CollisionPoint = ToMonoGame.Vector(allResults.HitPointWorld[i]); results.Collisions[i].CollisionBody = (allResults.CollisionObjects[i].UserObject as BasicPhysicalBody).EcsComponent; } } } // finally, return parsed results return(results); }