CharacterContactPositionState TrySupportLocation(ConvexCollidable <CylinderShape> queryObject, ref Vector3 position, out float hintOffset, ref QuickList <CharacterContact> tractionContacts, ref QuickList <CharacterContact> supportContacts, ref QuickList <CharacterContact> sideContacts, ref QuickList <CharacterContact> headContacts) { hintOffset = 0; PrepareQueryObject(queryObject, ref position); QueryManager.QueryContacts(queryObject, ref tractionContacts, ref supportContacts, ref sideContacts, ref headContacts, true); bool obstructed = IsObstructed(ref sideContacts, ref headContacts); if (obstructed) { return(CharacterContactPositionState.Obstructed); } if (supportContacts.Count > 0) { CharacterContactPositionState supportState; CharacterContact supportContact; QueryManager.AnalyzeSupportState(ref tractionContacts, ref supportContacts, out supportState, out supportContact); var down = characterBody.orientationMatrix.Down; //Note that traction is not tested for; it isn't important for the stance manager. if (supportState == CharacterContactPositionState.Accepted) { //We're done! The guess found a good spot to stand on. //We need to have fairly good contacts after this process, so only push it up a bit. hintOffset = Math.Min(0, Vector3.Dot(supportContact.Contact.Normal, down) * (CollisionDetectionSettings.AllowedPenetration * .5f - supportContact.Contact.PenetrationDepth)); return(CharacterContactPositionState.Accepted); } else if (supportState == CharacterContactPositionState.TooDeep) { //Looks like we have to keep trying, but at least we found a good hint. hintOffset = Math.Min(0, Vector3.Dot(supportContact.Contact.Normal, down) * (CollisionDetectionSettings.AllowedPenetration * .5f - supportContact.Contact.PenetrationDepth)); return(CharacterContactPositionState.TooDeep); } else //if (supportState == SupportState.Separated) { //It's not obstructed, but the support isn't quite right. //It's got a negative penetration depth. //We can use that as a hint. hintOffset = -.001f - Vector3.Dot(supportContact.Contact.Normal, down) * supportContact.Contact.PenetrationDepth; return(CharacterContactPositionState.NoHit); } } else //Not obstructed, but no support. { return(CharacterContactPositionState.NoHit); } }
public override void Initialize(Collidable newCollidableA, Collidable newCollidableB) { convex = newCollidableA as ConvexCollidable; triangle = newCollidableB as ConvexCollidable <TriangleShape>; if (convex == null || triangle == null) { convex = newCollidableB as ConvexCollidable; triangle = newCollidableA as ConvexCollidable <TriangleShape>; if (convex == null || triangle == null) { throw new ArgumentException("Inappropriate types used to initialize contact manifold."); } } pairTester.Initialize(convex.Shape); }
/// <summary> /// Constructs a stance manager for a character. /// </summary> /// <param name="characterBody">The character's body entity.</param> /// <param name="crouchingHeight">Crouching height of the character.</param> /// <param name="proneHeight">Prone height of the character.</param> /// <param name="queryManager">Provider of queries used by the stance manager to test if it is okay to change stances.</param> /// <param name="supportFinder">Support finder used by the character.</param> public StanceManager(Cylinder characterBody, float crouchingHeight, float proneHeight, QueryManager queryManager, SupportFinder supportFinder) { this.QueryManager = queryManager; this.SupportFinder = supportFinder; this.characterBody = characterBody; standingHeight = characterBody.Height; if (crouchingHeight < standingHeight) { this.crouchingHeight = crouchingHeight; } else { throw new ArgumentException("Crouching height must be less than standing height."); } if (proneHeight < crouchingHeight) { this.proneHeight = proneHeight; } else { throw new ArgumentException("Prone height must be less than crouching height."); } //We can share the real shape with the query objects. currentQueryObject = new ConvexCollidable <CylinderShape>(characterBody.CollisionInformation.Shape); standingQueryObject = new ConvexCollidable <CylinderShape>(new CylinderShape(StandingHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); crouchingQueryObject = new ConvexCollidable <CylinderShape>(new CylinderShape(CrouchingHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); proneQueryObject = new ConvexCollidable <CylinderShape>(new CylinderShape(proneHeight, characterBody.Radius) { CollisionMargin = currentQueryObject.Shape.CollisionMargin }); //Share the collision rules between the main body and its query objects. That way, the character's queries return valid results. currentQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; standingQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; crouchingQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; proneQueryObject.CollisionRules = characterBody.CollisionInformation.CollisionRules; }
///<summary> /// Initializes the pair handler. ///</summary> ///<param name="entryA">First entry in the pair.</param> ///<param name="entryB">Second entry in the pair.</param> public override void Initialize(BroadPhaseEntry entryA, BroadPhaseEntry entryB) { box = entryA as ConvexCollidable <BoxShape>; sphere = entryB as ConvexCollidable <SphereShape>; if (box == null || sphere == null) { box = entryB as ConvexCollidable <BoxShape>; sphere = entryA as ConvexCollidable <SphereShape>; if (box == null || sphere == null) { throw new ArgumentException("Inappropriate types used to initialize pair."); } } //Reorder the entries so that the guarantee that the normal points from A to B is satisfied. broadPhaseOverlap.entryA = box; broadPhaseOverlap.entryB = sphere; base.Initialize(entryA, entryB); }
///<summary> /// Initializes the pair handler. ///</summary> ///<param name="entryA">First entry in the pair.</param> ///<param name="entryB">Second entry in the pair.</param> public override void Initialize(BroadPhaseEntry entryA, BroadPhaseEntry entryB) { triangle = entryA as ConvexCollidable <TriangleShape>; convex = entryB as ConvexCollidable; if (triangle == null || convex == null) { triangle = entryB as ConvexCollidable <TriangleShape>; convex = entryA as ConvexCollidable; if (triangle == null || convex == null) { throw new ArgumentException("Inappropriate types used to initialize pair."); } } //Contact normal goes from A to B. broadPhaseOverlap.entryA = convex; broadPhaseOverlap.entryB = triangle; base.Initialize(entryA, entryB); }
///<summary> /// Initializes the pair handler. ///</summary> ///<param name="entryA">First entry in the pair.</param> ///<param name="entryB">Second entry in the pair.</param> public override void Initialize(BroadPhaseEntry entryA, BroadPhaseEntry entryB) { terrain = entryA as Terrain; convex = entryB as ConvexCollidable; if (terrain == null || convex == null) { terrain = entryB as Terrain; convex = entryA as ConvexCollidable; if (terrain == null || convex == null) { throw new ArgumentException("Inappropriate types used to initialize pair."); } } //Contact normal goes from A to B. broadPhaseOverlap.entryA = convex; broadPhaseOverlap.entryB = terrain; UpdateMaterialProperties(convex.entity != null ? convex.entity.material : null, terrain.material); base.Initialize(entryA, entryB); }
///<summary> /// Cleans up the manifold. ///</summary> public override void CleanUp() { boxA = null; boxB = null; base.CleanUp(); }
///<summary> /// Cleans up the pair handler. ///</summary> public override void CleanUp() { base.CleanUp(); convexInfo = null; }
public override void CleanUp() { base.CleanUp(); convex = null; checkContainment = true; }
///<summary> /// Cleans up the pair handler. ///</summary> public override void CleanUp() { base.CleanUp(); instancedMesh = null; convex = null; }