/PhysicsEngines/JigLib/JigLibController.cs
C# | 476 lines | 279 code | 58 blank | 139 comment | 9 complexity | e1ae7160653231ee07340271352e9395 MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using System.Collections.Generic;
- using Delta.Engine.Game.Interfaces;
- using Delta.Utilities.Datatypes;
- using Delta.Utilities.Helpers;
- using JigLibX.Collision;
- using JigLibX.Physics;
-
- namespace Delta.PhysicsEngines.JigLib
- {
- /// <summary>
- /// Class that is used to control a physical object with JigLib.
- /// </summary>
- internal class JigLibController
- : Controller,
- IController
- {
- #region Attachable (Public)
- /// <summary>
- /// Gets or Sets the attachable that is controlled.
- /// </summary>
- public IAttachable Attachable
- {
- get;
- set;
- }
- #endregion
-
- #region MovingDirection (Public)
- /// <summary>
- /// Gets or Sets the moving direction of the PhysicsBody.
- /// </summary>
- public Vector MovingDirection
- {
- get;
- set;
- }
- #endregion
-
- #region MoveSpeed (Public)
- /// <summary>
- /// Gets or Sets the speed at which the PhysicsBody moves.
- /// </summary>
- public float MoveSpeed
- {
- get;
- set;
- }
- #endregion
-
- #region JumpStrength (Public)
- /// <summary>
- /// Gets or Sets the measure of the strength that the PhysicsBody jumps.
- /// </summary>
- public float JumpStrength
- {
- get;
- set;
- }
- #endregion
-
- #region MaxUpSpeed (Public)
- /// <summary>
- /// Maximum up speed
- /// </summary>
- public float MaxUpSpeed
- {
- get;
- set;
- }
- #endregion
-
- #region AllowedGroundDistance (Public)
- /// <summary>
- /// Allowed distance to ground
- /// </summary>
- public float AllowedGroundDistance
- {
- get;
- set;
- }
- #endregion
-
- #region ForwardDirection (Public)
- /// <summary>
- /// Forward direction
- /// </summary>
- public Vector ForwardDirection
- {
- get;
- private set;
- }
- #endregion
-
- #region RightDirection (Public)
- /// <summary>
- /// Right direction
- /// </summary>
- public Vector RightDirection
- {
- get;
- private set;
- }
- #endregion
-
- #region BackwardDirection (Public)
- /// <summary>
- /// Backward direction, stored for faster accesss
- /// </summary>
- public Vector BackwardDirection
- {
- get;
- private set;
- }
- #endregion
-
- #region LeftDirection (Public)
- /// <summary>
- /// Left direction, stored for faster accesss
- /// </summary>
- public Vector LeftDirection
- {
- get;
- private set;
- }
- #endregion
-
- #region UpDirection (Public)
- /// <summary>
- /// Right direction, stored for faster accesss
- /// </summary>
- public Vector UpDirection
- {
- get;
- private set;
- }
- #endregion
-
- #region Private
-
- #region physicsManager (Private)
- private JigLibPhysics physicsManager;
- #endregion
-
- #region extImpulse (Private)
- /// <summary>
- /// External impulse applied to the ControlledObject (usually from jump).
- /// </summary>
- private Vector extImpulse = Vector.Zero;
- #endregion
-
- #region controlledBody (Private)
- /// <summary>
- /// The object that is controlled by the class
- /// </summary>
- private readonly JigLibBody controlledBody;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create a Controller using Jiglib
- /// </summary>
- /// <param name="physicsManager">The physics manager.</param>
- /// <param name="setControlledObject">The set controlled object.</param>
- public JigLibController(
- JigLibPhysics physicsManager,
- JigLibBody setControlledObject)
- :
- this(physicsManager, setControlledObject, 1, 1, 1,
- Vector.UnitX + Vector.UnitY, Vector.UnitX - Vector.UnitY)
- {
- }
-
- /// <summary>
- /// Create a Controller using Jiglib
- /// </summary>
- /// <param name="physicsManager">The physics manager.</param>
- /// <param name="setControlledObject">The set controlled object.</param>
- /// <param name="setMoveSpeed">Moving speed</param>
- /// <param name="setJumpStrength">Jump strength</param>
- /// <param name="allowedGroundDistance">The allowed ground distance.</param>
- public JigLibController(JigLibPhysics physicsManager,
- JigLibBody setControlledObject,
- float setMoveSpeed, float setJumpStrength, float allowedGroundDistance)
- :
- this(physicsManager, setControlledObject, setMoveSpeed,
- setJumpStrength, allowedGroundDistance, Vector.UnitX + Vector.UnitY,
- Vector.UnitX - Vector.UnitY)
- {
- }
-
- // JiglibController()
-
- /// <summary>
- /// Create a Controller using Jiglib
- /// </summary>
- /// <param name="physicsManager">The physics manager.</param>
- /// <param name="setControlledObject">The set controlled object.</param>
- /// <param name="setMoveSpeed">The set move speed.</param>
- /// <param name="setJumpStrength">The set jump strength.</param>
- /// <param name="allowedGroundDistance">The allowed ground distance.</param>
- /// <param name="setForwardDirection">The set forward direction.</param>
- /// <param name="setRightDirection">The set right direction.</param>
- public JigLibController(JigLibPhysics physicsManager,
- JigLibBody setControlledObject,
- float setMoveSpeed, float setJumpStrength, float allowedGroundDistance,
- Vector setForwardDirection, Vector setRightDirection)
- : this(physicsManager, setControlledObject, setMoveSpeed,
- setJumpStrength, 1.0f, allowedGroundDistance, setForwardDirection,
- setRightDirection)
- {
- }
-
- // JiglibController()
-
- /// <summary>
- /// Create a Controller using Jiglib
- /// </summary>
- /// <param name="physicsManager">The physics manager.</param>
- /// <param name="setControlledObject">The set controlled object.</param>
- /// <param name="setMoveSpeed">The set move speed.</param>
- /// <param name="setJumpStrength">The set jump strength.</param>
- /// <param name="setMaxUpSpeed">The set max up speed.</param>
- /// <param name="allowedGroundDistance">The allowed ground distance.</param>
- /// <param name="setForwardDirection">The set forward direction.</param>
- /// <param name="setRightDirection">The set right direction.</param>
- public JigLibController(JigLibPhysics physicsManager,
- JigLibBody setControlledObject,
- float setMoveSpeed, float setJumpStrength, float setMaxUpSpeed,
- float allowedGroundDistance, Vector setForwardDirection,
- Vector setRightDirection)
- {
- //Input.InputInstance.CommandEvent += new InputEventDelegate(OnInputEvent);
-
- this.physicsManager = physicsManager;
-
- MoveSpeed = setMoveSpeed;
- JumpStrength = setJumpStrength;
- MaxUpSpeed = setMaxUpSpeed;
- AllowedGroundDistance = allowedGroundDistance;
-
- ForwardDirection = setForwardDirection;
- ForwardDirection.Normalize();
- BackwardDirection = Vector.Zero - ForwardDirection;
- BackwardDirection.Normalize();
- RightDirection = setRightDirection;
- RightDirection.Normalize();
- LeftDirection = Vector.Zero - RightDirection;
- LeftDirection.Normalize();
-
- CalculateUpDirection();
-
- MovingDirection = Vector.Zero;
-
- controlledBody = setControlledObject;
-
- EnableController();
- }
- #endregion
-
- #region UpdateController (Public)
- /// <summary>
- /// UpdateController is inherited from JigLib Controller and
- /// allows direct manipulation of the physic state of an object. Here
- /// is used to update the position of the ControlledObject according to
- /// user input.
- /// </summary>
- /// <param name="dt">Delta time to update controller.</param>
- public override void UpdateController(float dt)
- {
- // controlled objects should always be active!!!
- controlledBody.Body.SetActive();
-
- ApplyMovementDirect();
-
- controlledBody.Body.ApplyWorldImpulse(
- JigLibDatatypesMapping.Convert(ref extImpulse));
-
- // reset internal variables
- ResetInternalMovementData();
- }
- #endregion
-
- #region Methods (Private)
-
- #region ResetInternalMovementData
- /// <summary>
- /// Reset internal movement data
- /// </summary>
- private void ResetInternalMovementData()
- {
- MovingDirection = extImpulse = Vector.Zero;
- }
- #endregion
-
- // ResetInternalMovementData()
-
- #region ApplyMovementDirect
- /// <summary>
- /// Apply the movement components directly in the objects velocity
- /// </summary>
- private void ApplyMovementDirect()
- {
- // get the vertical component of the velocity
- float verticalVelocity = Vector.Dot(UpDirection,
- controlledBody.LinearVelocity);
-
- MaxUpSpeed = 1.0f;
-
- // limit the up velocity to avoid huge jumps
- float upSpeed = verticalVelocity >= MaxUpSpeed
- ? MaxUpSpeed
- : verticalVelocity;
-
- // calculate final upVelocity
- Vector upVelocity = upSpeed * UpDirection;
-
- // see if we got a moving direction
- if (MovingDirection.Length <= 0.00001f)
- {
- //if (CheckOnAirCollisionNormal())
- if (CheckOnAirRayCast())
- {
- // keep the vertical component of the speed
- //controlledObject.Velocity = controlledObject.Velocity;
- }
- else
- {
- // stop the object
- controlledBody.LinearVelocity = Vector.Zero;
- }
- } // if
- else
- {
- MovingDirection.Normalize();
- //float damp = 1.0f;// 10.0f * dt;
-
- //if (CheckOnAirCollisionNormal())
- if (CheckOnAirRayCast())
- {
- if (HasCollisions())
- {
- //controlledObject.Velocity -= verticalVelocity * UpDirection;
- //controlledObject.Velocity += upVelocity;
- //controlledObject.Velocity += 0.01f * MoveSpeed * movingDirection;
-
- //controlledObject.Velocity -= damp * verticalVelocity * UpDirection;
- }
- else
- {
- controlledBody.LinearVelocity = upVelocity;
- controlledBody.LinearVelocity += MoveSpeed * MovingDirection;
- }
- } // if
- else
- {
- //movingDirection = Vector.Normalize(movingDirection);
- controlledBody.LinearVelocity = MoveSpeed * MovingDirection;
- //controlledObject.Velocity = upVelocity;
- //controlledObject.Velocity += MoveSpeed * movingDirection;
- }
- }
- }
- #endregion
-
- #region HasCollisions
- /// <summary>
- /// Has collisions
- /// </summary>
- /// <returns>True if has collisions, false otherwise.</returns>
- private bool HasCollisions()
- {
- return controlledBody.Skin.Collisions.Count > 0;
- }
- #endregion
-
- #region CheckOnAirCollisionNormal
- /// <summary>
- /// Check if the ControlledObject is on air, i.e. does not collide with
- /// anything on the ground, by inspecting the normal of colliding geometries
- /// </summary>
- /// <returns>True if on air false otherwise.</returns>
- private bool CheckOnAirCollisionNormal()
- {
- List<CollisionInfo> collisionInfo =
- controlledBody.Skin.Collisions;
-
- bool isOnAir = true;
-
- if (collisionInfo.Count > 0)
- {
- for (int i = 0; i < collisionInfo.Count; i++)
- {
- CollisionInfo info = collisionInfo[i];
- Vector dirToBody;
- JigLibDatatypesMapping.Convert(info.DirToBody0, out dirToBody);
- dirToBody.Normalize();
-
- //Vector groundSupport = dirToBody;//+= DirToBody;
-
- // if the collision normal has an angle bigger than 30 degrees
- // then we consider that the body can "support" on this
- if (Vector.Dot(dirToBody, UpDirection) > 0.866f)
- {
- // adjust the moving direction according to the slope of the ground
- Vector helpVec = Vector.Cross(MovingDirection, UpDirection);
- MovingDirection = Vector.Cross(dirToBody, helpVec);
- return false;
- }
- }
- }
-
- return isOnAir;
- }
- #endregion
-
- #region CheckOnAirRayCast
- /// <summary>
- /// Check if object is on the air, i.e. does not collide with
- /// anything on the ground, using ray casting.
- /// </summary>
- /// <returns>True if any intersection happen, false otherwise.</returns>
- private bool CheckOnAirRayCast()
- {
- //float distToFloorSquare = AllowedGroundDistance * AllowedGroundDistance;
-
- Vector position = controlledBody.Position;
- Vector normal; // = new Vector();
- float fractions;
- Object userData;
- Ray downRay = new Ray(position, Vector.Zero - UpDirection);
- PhysicsBody castObjects;
- if (Physics.FindRayCast(
- downRay, true, out castObjects, out normal, out fractions, out userData))
- {
- Vector[] rayContacts = userData as Vector[];
-
- // Threat only first element.
- Vector rayContact = rayContacts[0];
-
- // project the distance to the surface normal so that we can walk
- // on inclined ground
- normal = Vector.Normalize(normal);
- Vector vertical = position - rayContact;
- float projection = MathHelper.Abs(Vector.Dot(vertical, normal));
- float penetration = AllowedGroundDistance - projection;
- if (penetration > 0.0f)
- {
- // quick hack for not allowing the controlled object to actually
- // pass through the ground
- controlledBody.Position += penetration * UpDirection; // normal;
- return false;
- }
- }
-
- return true;
- }
- #endregion
-
- #region CalculateUpDirection
- /// <summary>
- /// Calculate new up direction
- /// </summary>
- private void CalculateUpDirection()
- {
- UpDirection = Vector.Cross(RightDirection, ForwardDirection);
-
- UpDirection = Vector.Normalize(UpDirection);
- }
- #endregion
-
- #endregion
- }
- }