| 1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// | 
|---|
| 2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// | 
|---|
| 3 | #pragma once | 
|---|
| 4 |  | 
|---|
| 5 | #include "BsCorePrerequisites.h" | 
|---|
| 6 | #include "Physics/BsPhysicsCommon.h" | 
|---|
| 7 | #include "Math/BsVector3.h" | 
|---|
| 8 |  | 
|---|
| 9 | namespace bs | 
|---|
| 10 | { | 
|---|
| 11 | class PhysicsScene; | 
|---|
| 12 |  | 
|---|
| 13 | /** @addtogroup Physics | 
|---|
| 14 | *  @{ | 
|---|
| 15 | */ | 
|---|
| 16 |  | 
|---|
| 17 | /** | 
|---|
| 18 | * Controls climbing behaviour for a capsule character controller. Normally the character controller will not | 
|---|
| 19 | * automatically climb when heights are greater than the assigned step offset. However due to the shape of the capsule | 
|---|
| 20 | * it might automatically climb over slightly larger heights than assigned step offsets. | 
|---|
| 21 | */ | 
|---|
| 22 | enum class BS_SCRIPT_EXPORT(m:Physics) CharacterClimbingMode | 
|---|
| 23 | { | 
|---|
| 24 | Normal, /**< Normal behaviour. Capsule character controller will be able to auto-step even above the step offset. */ | 
|---|
| 25 | Constrained /**< The system will attempt to limit auto-step to the provided step offset and no higher. */ | 
|---|
| 26 | }; | 
|---|
| 27 |  | 
|---|
| 28 | /** Controls behaviour when a character controller reaches a slope thats larger than its slope offset. */ | 
|---|
| 29 | enum class BS_SCRIPT_EXPORT(m:Physics) CharacterNonWalkableMode | 
|---|
| 30 | { | 
|---|
| 31 | Prevent, /**< Character will be prevented from going further, but will be allowed to move laterally. */ | 
|---|
| 32 | PreventAndSlide /**< Character will be prevented from going further, but also slide down the slope. */ | 
|---|
| 33 | }; | 
|---|
| 34 |  | 
|---|
| 35 | /** Reports in which directions is the character colliding with other objects. */ | 
|---|
| 36 | enum class BS_SCRIPT_EXPORT(m:Physics) CharacterCollisionFlag | 
|---|
| 37 | { | 
|---|
| 38 | Sides = 0x1, /**< Character is colliding with its sides. */ | 
|---|
| 39 | Up = 0x2, /**< Character is colliding with the ceiling. */ | 
|---|
| 40 | Down = 0x4 /**< Character is colliding with the ground. */ | 
|---|
| 41 | }; | 
|---|
| 42 |  | 
|---|
| 43 | /** @copydoc CharacterCollisionFlag */ | 
|---|
| 44 | typedef Flags<CharacterCollisionFlag> CharacterCollisionFlags; | 
|---|
| 45 | BS_FLAGS_OPERATORS(CharacterCollisionFlag) | 
|---|
| 46 |  | 
|---|
| 47 | struct CHAR_CONTROLLER_DESC; | 
|---|
| 48 | struct ControllerColliderCollision; | 
|---|
| 49 | struct ControllerControllerCollision; | 
|---|
| 50 |  | 
|---|
| 51 | /** | 
|---|
| 52 | * Special physics controller meant to be used for game characters. Uses the "slide-and-collide" physics instead of | 
|---|
| 53 | * of the standard physics model to handle various issues with manually moving kinematic objects. Uses a capsule to | 
|---|
| 54 | * represent the character's bounds. | 
|---|
| 55 | */ | 
|---|
| 56 | class BS_CORE_EXPORT CharacterController | 
|---|
| 57 | { | 
|---|
| 58 | public: | 
|---|
| 59 | CharacterController(const CHAR_CONTROLLER_DESC& desc) { } | 
|---|
| 60 | virtual ~CharacterController() { } | 
|---|
| 61 |  | 
|---|
| 62 | /** | 
|---|
| 63 | * Moves the controller in the specified direction by the specified amount, while interacting with surrounding | 
|---|
| 64 | * geometry. Returns flags signaling where collision occurred after the movement. | 
|---|
| 65 | * | 
|---|
| 66 | * Does not account for gravity, you must apply it manually. | 
|---|
| 67 | */ | 
|---|
| 68 | virtual CharacterCollisionFlags move(const Vector3& displacement) = 0; | 
|---|
| 69 |  | 
|---|
| 70 | /** Returns position of the center of the controller. */ | 
|---|
| 71 | virtual Vector3 getPosition() const = 0; | 
|---|
| 72 |  | 
|---|
| 73 | /** | 
|---|
| 74 | * Sets position of the center of the controller. This will teleport the character to the location. Use move() | 
|---|
| 75 | * for movement that includes physics. | 
|---|
| 76 | */ | 
|---|
| 77 | virtual void setPosition(const Vector3& position) = 0; | 
|---|
| 78 |  | 
|---|
| 79 | /** @copydoc setFootPosition() */ | 
|---|
| 80 | virtual Vector3 () const = 0; | 
|---|
| 81 |  | 
|---|
| 82 | /** | 
|---|
| 83 | * Determines the  position of the bottom of the controller. Position takes contact offset into account. Changing | 
|---|
| 84 | * this will teleport the character to the location. Use move() for movement that includes physics. | 
|---|
| 85 | */ | 
|---|
| 86 | virtual void (const Vector3& position) = 0; | 
|---|
| 87 |  | 
|---|
| 88 | /** @copydoc setRadius() */ | 
|---|
| 89 | virtual float getRadius() const = 0; | 
|---|
| 90 |  | 
|---|
| 91 | /** Determines the radius of the controller capsule. */ | 
|---|
| 92 | virtual void setRadius(float radius) = 0; | 
|---|
| 93 |  | 
|---|
| 94 | /** @copydoc setHeight() */ | 
|---|
| 95 | virtual float getHeight() const = 0; | 
|---|
| 96 |  | 
|---|
| 97 | /** Determines the height between the centers of the two spheres of the controller capsule. */ | 
|---|
| 98 | virtual void setHeight(float height) = 0; | 
|---|
| 99 |  | 
|---|
| 100 | /** @copydoc setUp() */ | 
|---|
| 101 | virtual Vector3 getUp() const = 0; | 
|---|
| 102 |  | 
|---|
| 103 | /** Determines the up direction of capsule. Determines capsule orientation. */ | 
|---|
| 104 | virtual void setUp(const Vector3& up) = 0; | 
|---|
| 105 |  | 
|---|
| 106 | /** @copydoc CHAR_CONTROLLER_DESC::climbingMode */ | 
|---|
| 107 | virtual CharacterClimbingMode getClimbingMode() const = 0; | 
|---|
| 108 |  | 
|---|
| 109 | /** @copydoc CHAR_CONTROLLER_DESC::climbingMode */ | 
|---|
| 110 | virtual void setClimbingMode(CharacterClimbingMode mode) = 0; | 
|---|
| 111 |  | 
|---|
| 112 | /** @copydoc CHAR_CONTROLLER_DESC::nonWalkableMode */ | 
|---|
| 113 | virtual CharacterNonWalkableMode getNonWalkableMode() const = 0; | 
|---|
| 114 |  | 
|---|
| 115 | /** @copydoc CHAR_CONTROLLER_DESC::nonWalkableMode */ | 
|---|
| 116 | virtual void setNonWalkableMode(CharacterNonWalkableMode mode) = 0; | 
|---|
| 117 |  | 
|---|
| 118 | /** @copydoc CHAR_CONTROLLER_DESC::minMoveDistance */ | 
|---|
| 119 | virtual float getMinMoveDistance() const = 0; | 
|---|
| 120 |  | 
|---|
| 121 | /** @copydoc CHAR_CONTROLLER_DESC::minMoveDistance */ | 
|---|
| 122 | virtual void setMinMoveDistance(float value) = 0; | 
|---|
| 123 |  | 
|---|
| 124 | /** @copydoc CHAR_CONTROLLER_DESC::contactOffset */ | 
|---|
| 125 | virtual float getContactOffset() const = 0; | 
|---|
| 126 |  | 
|---|
| 127 | /** @copydoc CHAR_CONTROLLER_DESC::contactOffset */ | 
|---|
| 128 | virtual void setContactOffset(float value) = 0; | 
|---|
| 129 |  | 
|---|
| 130 | /** @copydoc CHAR_CONTROLLER_DESC::stepOffset */ | 
|---|
| 131 | virtual float getStepOffset() const = 0; | 
|---|
| 132 |  | 
|---|
| 133 | /** @copydoc CHAR_CONTROLLER_DESC::stepOffset */ | 
|---|
| 134 | virtual void setStepOffset(float value) = 0; | 
|---|
| 135 |  | 
|---|
| 136 | /** @copydoc CHAR_CONTROLLER_DESC::slopeLimit */ | 
|---|
| 137 | virtual Radian getSlopeLimit() const = 0; | 
|---|
| 138 |  | 
|---|
| 139 | /** @copydoc CHAR_CONTROLLER_DESC::slopeLimit */ | 
|---|
| 140 | virtual void setSlopeLimit(Radian value) = 0; | 
|---|
| 141 |  | 
|---|
| 142 | /** Determines the layer that controls what can the controller collide with. */ | 
|---|
| 143 | virtual void setLayer(UINT64 layer) { mLayer = layer; } | 
|---|
| 144 |  | 
|---|
| 145 | /** @copydoc setLayer() */ | 
|---|
| 146 | virtual UINT64 getLayer() const { return mLayer; } | 
|---|
| 147 |  | 
|---|
| 148 | /** | 
|---|
| 149 | * Creates a new character controller. | 
|---|
| 150 | * | 
|---|
| 151 | * @param[in]	scene		Scene to add the controller to. | 
|---|
| 152 | * @param[in]	desc		Describes controller geometry and movement. | 
|---|
| 153 | */ | 
|---|
| 154 | static SPtr<CharacterController> create(PhysicsScene& scene, const CHAR_CONTROLLER_DESC& desc); | 
|---|
| 155 |  | 
|---|
| 156 | /** Triggered when the controller hits a collider. */ | 
|---|
| 157 | Event<void(const ControllerColliderCollision&)> onColliderHit; | 
|---|
| 158 |  | 
|---|
| 159 | /** Triggered when the controller hits another character controller. */ | 
|---|
| 160 | Event<void(const ControllerControllerCollision&)> onControllerHit; | 
|---|
| 161 |  | 
|---|
| 162 | /** @name Internal | 
|---|
| 163 | *  @{ | 
|---|
| 164 | */ | 
|---|
| 165 |  | 
|---|
| 166 | /** | 
|---|
| 167 | * Sets the object that owns this physics object, if any. Used for high level systems so they can easily map their | 
|---|
| 168 | * high level physics objects from the low level ones returned by various queries and events. | 
|---|
| 169 | */ | 
|---|
| 170 | void _setOwner(PhysicsOwnerType type, void* owner) { mOwner.type = type; mOwner.ownerData = owner; } | 
|---|
| 171 |  | 
|---|
| 172 | /** | 
|---|
| 173 | * Gets the object that owns this physics object, if any. Used for high level systems so they can easily map their | 
|---|
| 174 | * high level physics objects from the low level ones returned by various queries and events. | 
|---|
| 175 | */ | 
|---|
| 176 | void* _getOwner(PhysicsOwnerType type) const { return mOwner.type == type ? mOwner.ownerData : nullptr; } | 
|---|
| 177 |  | 
|---|
| 178 | /** @} */ | 
|---|
| 179 | private: | 
|---|
| 180 | PhysicsObjectOwner mOwner; | 
|---|
| 181 | UINT64 mLayer = 1; | 
|---|
| 182 | }; | 
|---|
| 183 |  | 
|---|
| 184 | /** Contains all the information required for initializing a character controller. */ | 
|---|
| 185 | struct CHAR_CONTROLLER_DESC | 
|---|
| 186 | { | 
|---|
| 187 | /** Center of the controller capsule */ | 
|---|
| 188 | Vector3 position = Vector3::ZERO; | 
|---|
| 189 |  | 
|---|
| 190 | /** | 
|---|
| 191 | * Contact offset specifies a skin around the object within which contacts will be generated. It should be a small | 
|---|
| 192 | * positive non-zero value. | 
|---|
| 193 | */ | 
|---|
| 194 | float contactOffset = 0.1f; | 
|---|
| 195 |  | 
|---|
| 196 | /** | 
|---|
| 197 | * Controls which obstacles will the character be able to automatically step over without being stopped. This is the | 
|---|
| 198 | * height of the maximum obstacle that will be stepped over (with exceptions, see climbingMode). | 
|---|
| 199 | */ | 
|---|
| 200 | float stepOffset = 0.5f; | 
|---|
| 201 |  | 
|---|
| 202 | /** | 
|---|
| 203 | * Controls which slopes should the character consider too steep and won't be able to move over. See | 
|---|
| 204 | * nonWalkableMode for more information. | 
|---|
| 205 | */ | 
|---|
| 206 | Radian slopeLimit = Degree(45.0f); | 
|---|
| 207 |  | 
|---|
| 208 | /** | 
|---|
| 209 | * Represents minimum distance that the character will move during a call to move(). This is used to stop the | 
|---|
| 210 | * recursive motion algorithm when the remaining distance is too small. | 
|---|
| 211 | */ | 
|---|
| 212 | float minMoveDistance = 0.0f; | 
|---|
| 213 |  | 
|---|
| 214 | /** Height between the centers of the two spheres of the controller capsule. */ | 
|---|
| 215 | float height = 1.0f; | 
|---|
| 216 |  | 
|---|
| 217 | /** Radius of the controller capsule. */ | 
|---|
| 218 | float radius = 1.0f; | 
|---|
| 219 |  | 
|---|
| 220 | /** Up direction of controller capsule. Determines capsule orientation. */ | 
|---|
| 221 | Vector3 up = Vector3::UNIT_Y; | 
|---|
| 222 |  | 
|---|
| 223 | /** | 
|---|
| 224 | * Controls what happens when character encounters a height higher than its step offset. | 
|---|
| 225 | * | 
|---|
| 226 | * @see	CharacterClimbingMode | 
|---|
| 227 | */ | 
|---|
| 228 | CharacterClimbingMode climbingMode = CharacterClimbingMode::Normal; | 
|---|
| 229 |  | 
|---|
| 230 | /** | 
|---|
| 231 | * Controls what happens when character encounters a slope higher than its slope offset. | 
|---|
| 232 | * | 
|---|
| 233 | * @see	CharacterNonWalkableMode | 
|---|
| 234 | */ | 
|---|
| 235 | CharacterNonWalkableMode nonWalkableMode = CharacterNonWalkableMode::Prevent; | 
|---|
| 236 | }; | 
|---|
| 237 |  | 
|---|
| 238 | /** Contains data about a collision of a character controller and another object. */ | 
|---|
| 239 | struct BS_SCRIPT_EXPORT(m:Physics,pl:true) ControllerCollision | 
|---|
| 240 | { | 
|---|
| 241 | Vector3 position; /**< Contact position. */ | 
|---|
| 242 | Vector3 normal; /**< Contact normal. */ | 
|---|
| 243 | Vector3 motionDir; /**< Direction of motion after the hit. */ | 
|---|
| 244 | float motionAmount; /**< Magnitude of motion after the hit. */ | 
|---|
| 245 | }; | 
|---|
| 246 |  | 
|---|
| 247 | /** Contains data about a collision of a character controller and a collider. */ | 
|---|
| 248 | struct BS_SCRIPT_EXPORT(m:Physics,pl:true) ControllerColliderCollision : ControllerCollision | 
|---|
| 249 | { | 
|---|
| 250 | /** | 
|---|
| 251 | * Component of the controller that was touched. Can be null if the controller has no component parent, in which | 
|---|
| 252 | * case check #colliderRaw. | 
|---|
| 253 | */ | 
|---|
| 254 | HCollider collider; | 
|---|
| 255 |  | 
|---|
| 256 | BS_SCRIPT_EXPORT(ex:true) | 
|---|
| 257 | Collider* colliderRaw; /**< Collider that was touched. */ | 
|---|
| 258 | UINT32 triangleIndex; /**< Touched triangle index for mesh colliders. */ | 
|---|
| 259 | }; | 
|---|
| 260 |  | 
|---|
| 261 | /** Contains data about a collision between two character controllers. */ | 
|---|
| 262 | struct BS_SCRIPT_EXPORT(m:Physics,pl:true) ControllerControllerCollision : ControllerCollision | 
|---|
| 263 | { | 
|---|
| 264 | /** | 
|---|
| 265 | * Component of the controller that was touched. Can be null if the controller has no component parent, in which | 
|---|
| 266 | * case check #controllerRaw. | 
|---|
| 267 | */ | 
|---|
| 268 | HCharacterController controller; | 
|---|
| 269 |  | 
|---|
| 270 | BS_SCRIPT_EXPORT(ex:true) | 
|---|
| 271 | CharacterController* controllerRaw; /**< Controller that was touched. */ | 
|---|
| 272 | }; | 
|---|
| 273 |  | 
|---|
| 274 | /** @} */ | 
|---|
| 275 | } | 
|---|