소스 검색

Abstract interface for character controller
Added a helper Flags class for easier manipulation of bitwise flags

BearishSun 9 년 전
부모
커밋
ae720a53b2

+ 2 - 0
BansheeCore/BansheeCore.vcxproj

@@ -309,6 +309,7 @@
     <ClInclude Include="Include\BsCDistanceJoint.h" />
     <ClInclude Include="Include\BsCDistanceJoint.h" />
     <ClInclude Include="Include\BsCDistanceJointRTTI.h" />
     <ClInclude Include="Include\BsCDistanceJointRTTI.h" />
     <ClInclude Include="Include\BsCFixedJointRTTI.h" />
     <ClInclude Include="Include\BsCFixedJointRTTI.h" />
+    <ClInclude Include="Include\BsCharacterController.h" />
     <ClInclude Include="Include\BsCHingeJoint.h" />
     <ClInclude Include="Include\BsCHingeJoint.h" />
     <ClInclude Include="Include\BsCHingeJointRTTI.h" />
     <ClInclude Include="Include\BsCHingeJointRTTI.h" />
     <ClInclude Include="Include\BsCJointRTTI.h" />
     <ClInclude Include="Include\BsCJointRTTI.h" />
@@ -519,6 +520,7 @@
     <ClCompile Include="Source\BsCD6Joint.cpp" />
     <ClCompile Include="Source\BsCD6Joint.cpp" />
     <ClCompile Include="Source\BsCDistanceJoint.cpp" />
     <ClCompile Include="Source\BsCDistanceJoint.cpp" />
     <ClCompile Include="Source\BsCFixedJoint.cpp" />
     <ClCompile Include="Source\BsCFixedJoint.cpp" />
+    <ClCompile Include="Source\BsCharacterController.cpp" />
     <ClCompile Include="Source\BsCHingeJoint.cpp" />
     <ClCompile Include="Source\BsCHingeJoint.cpp" />
     <ClCompile Include="Source\BsCJoint.cpp" />
     <ClCompile Include="Source\BsCJoint.cpp" />
     <ClCompile Include="Source\BsCMeshCollider.cpp" />
     <ClCompile Include="Source\BsCMeshCollider.cpp" />

+ 6 - 0
BansheeCore/BansheeCore.vcxproj.filters

@@ -746,6 +746,9 @@
     <ClInclude Include="Include\BsCD6JointRTTI.h">
     <ClInclude Include="Include\BsCD6JointRTTI.h">
       <Filter>Header Files\RTTI</Filter>
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsCharacterController.h">
+      <Filter>Header Files\Physics</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsCoreApplication.cpp">
     <ClCompile Include="Source\BsCoreApplication.cpp">
@@ -1180,5 +1183,8 @@
     <ClCompile Include="Source\BsCD6Joint.cpp">
     <ClCompile Include="Source\BsCD6Joint.cpp">
       <Filter>Source Files\Components</Filter>
       <Filter>Source Files\Components</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsCharacterController.cpp">
+      <Filter>Source Files\Physics</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 170 - 0
BansheeCore/Include/BsCharacterController.h

@@ -0,0 +1,170 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+#include "BsCorePrerequisites.h"
+#include "BsVector3.h"
+
+namespace BansheeEngine
+{
+	/** 
+	 * Controls climbing behaviour for a capsule character controller. Normally the character controller will not
+	 * automatically climb when heights are greater than the assigned step offset. However due to the shape of the capsule
+	 * it might automatically climb over slightly larger heights than assigned step offsets.
+	 */
+	enum class CharacterClimbingMode
+	{
+		Normal, /**< Normal behaviour. Capsule character controller will be able to auto-step over the step offset. */
+		Constrained /**< The system will attempt to limit auto-step to the provided step offset and no higher. */
+	};
+
+	/** Controls behaviour when a character controller reaches a slope thats larger than its slope offset. */
+	enum class CharacterNonWalkableMode
+	{
+		Prevent, /**< Character will be prevented from going further, but will be allowed to move laterally. */
+		PreventAndSlide /**< Character will be prevented from going further, but also slide down the slope. */
+	};
+
+	/** Reports in which directions is the character colliding with other objects */
+	enum class CharacterCollisionFlag
+	{
+		Sides = 0x1, /**< Character is colliding with its sides. */
+		Up = 0x2, /**< Character is colliding with the ceiling. */
+		Down = 0x4 /**< Character is colliding with the ground. */
+	};
+
+	/** @copydoc CharacterCollisionFlag */
+	typedef Flags<CharacterCollisionFlag> CharacterCollisionFlags;
+	BS_FLAGS_OPERATORS(CharacterCollisionFlag)
+
+	class BS_CORE_EXPORT CharacterController
+	{
+	public:
+		virtual ~CharacterController() { }
+
+		/**
+		 * Moves the controller in the specified direction by the specified amount, while interacting with surrounding
+		 * geometry. Returns flags signaling where collision occurred after the movement.
+		 */
+		virtual CharacterCollisionFlags move(const Vector3& displacement) = 0;
+
+		/** Returns position of the center of the controller. */
+		virtual Vector3 getPosition() const = 0;
+
+		/** 
+		 * Sets position of the center of the controller. This will teleport the character to the location. Use move()
+		 * for movement that includes physics.
+		 */
+		virtual void setPosition(const Vector3& position) = 0;
+
+		/** Returns position of the bottom of the controller. Position takes contact offset into account. */
+		virtual Vector3 getFootPosition() const = 0;
+
+		/** 
+		 * Sets position of the bottom of the controller. Position takes contact offset into account. This will teleport the
+		 * character to the location. Use move() for movement that includes physics.
+		 */
+		virtual void setFootPosition(const Vector3& position) = 0;
+
+		/** Returns the radius of the controller capsule. */
+		virtual float getRadius() const = 0;
+
+		/** Sets the radius of the controller capsule. */
+		virtual void setRadius(float radius) = 0;
+
+		/** Returns the height of the controller capsule. */
+		virtual float getHeight() const = 0;
+
+		/** Sets the height of the controller capsule. */
+		virtual void setHeight(float height) = 0;
+
+		/** Returns the up direction of capsule. Determines capsule orientation. */
+		virtual Vector3 getUp() const = 0;
+
+		/** Sets the up direction of capsule. Determines capsule orientation. */
+		virtual void setUp(const Vector3& up) = 0;
+
+		/** 
+		 * Returns climbing mode that controls what happens when character encounters a height higher than its step offset. 
+		 *
+		 * @see	CharacterClimbingMode
+		 */
+		virtual CharacterClimbingMode getClimbingMode() const = 0;
+
+		/** 
+		 * Sets climbing mode that controls what happens when character encounters a height higher than its step offset. 
+		 *
+		 * @see	CharacterClimbingMode
+		 */
+		virtual void setClimbingMode(CharacterClimbingMode mode) = 0;
+
+		/** 
+		 * Returns non walkable mode that controls what happens when character encounters a slope higher than its slope 
+		 * offset. 
+		 *
+		 * @see	CharacterNonWalkableMode
+		 */
+		virtual CharacterNonWalkableMode getNonWalkableMode() const = 0;
+
+		/** 
+		 * Sets non walkable mode that controls what happens when character encounters a slope higher than its slope 
+		 * offset. 
+		 *
+		 * @see	CharacterNonWalkableMode
+		 */
+		virtual void setNonWalkableMode(CharacterNonWalkableMode mode) = 0;
+
+		/** 
+		 * Returns minimum distance that the character will move during a call to move(). This is used to stop the recursive
+		 * motion algorithm when the remaining distance is too small.
+		 */
+		virtual float getMinMoveDistance() = 0;
+
+		/** 
+		 * Sets minimum distance that the character will move during a call to move(). This is used to stop the recursive
+		 * motion algorithm when the remaining distance is too small.
+		 */
+		virtual void setMinMoveDistance(float value) = 0;
+
+		/** 
+		 * Returns the contact offset value. Contact offset specifies a skin around the object within which contacts will
+		 * be generated. It should be a small positive non-zero value.
+		 */
+		virtual float getContactOffset() = 0;
+
+		/**
+		 * Sets the contact offset value. Contact offset specifies a skin around the object within which contacts will
+		 * be generated. It should be a small positive non-zero value.
+		 */
+		virtual void setContactOffset(float value) = 0;
+
+		/** 
+		 * Gets the step offset that controls which obstacles will the character be able to automatically step over without
+		 * being stopped. This is the height of the maximum obstacle that will be stepped over (with exceptions, see
+		 * setClimbingMode().
+		 */
+		virtual float getStepOffset() = 0;
+
+		/** 
+		 * Sets the step offset that controls which obstacles will the character be able to automatically step over without
+		 * being stopped. This is the height of the maximum obstacle that will be stepped over (with exceptions, see
+		 * setClimbingMode().
+		 */
+		virtual void setStepOffset(float value) = 0;
+
+		/**
+		 * Gets the slope angle that controls which slopes should the character consider too steep and won't be able to
+		 * move over. See setNonWalkableMode() for more information.
+		 */
+		virtual Radian getSlopeOffset() = 0;
+
+		/**
+		 * Sets the slope angle that controls which slopes should the character consider too steep and won't be able to
+		 * move over. See setNonWalkableMode() for more information.
+		 */
+		virtual void setSlopeOffset(Radian value) = 0;
+
+		/** Creates a new character controller. */
+		static SPtr<CharacterController> create();
+	};
+}

+ 1 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -259,6 +259,7 @@ namespace BansheeEngine
 	class SphericalJoint;
 	class SphericalJoint;
 	class SliderJoint;
 	class SliderJoint;
 	class D6Joint;
 	class D6Joint;
+	class CharacterController;
 	// Asset import
 	// Asset import
 	class SpecificImporter;
 	class SpecificImporter;
 	class Importer;
 	class Importer;

+ 3 - 0
BansheeCore/Include/BsPhysics.h

@@ -37,6 +37,9 @@ namespace BansheeEngine
 		virtual SPtr<SliderJoint> createSliderJoint() = 0;
 		virtual SPtr<SliderJoint> createSliderJoint() = 0;
 		virtual SPtr<D6Joint> createD6Joint() = 0;
 		virtual SPtr<D6Joint> createD6Joint() = 0;
 
 
+		/** @copydoc CharacterController::create */
+		virtual SPtr<CharacterController> createCharacterController() = 0;
+
 		void toggleCollision(UINT64 groupA, UINT64 groupB, bool enabled);
 		void toggleCollision(UINT64 groupA, UINT64 groupB, bool enabled);
 		bool isCollisionEnabled(UINT64 groupA, UINT64 groupB) const;
 		bool isCollisionEnabled(UINT64 groupA, UINT64 groupB) const;
 
 

+ 12 - 0
BansheeCore/Source/BsCharacterController.cpp

@@ -0,0 +1,12 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#include "BsCharacterController.h"
+#include "BsPhysics.h"
+
+namespace BansheeEngine
+{
+	SPtr<CharacterController> CharacterController::create()
+	{
+		return gPhysics().createCharacterController();
+	}
+}

+ 3 - 0
BansheePhysX/Include/BsPhysX.h

@@ -65,6 +65,9 @@ namespace BansheeEngine
 		SPtr<SliderJoint> createSliderJoint() override;
 		SPtr<SliderJoint> createSliderJoint() override;
 		SPtr<D6Joint> createD6Joint() override;
 		SPtr<D6Joint> createD6Joint() override;
 
 
+		/** @copydoc Physics::createCharacterController*/
+		SPtr<CharacterController> createCharacterController() override;
+
 		void _reportContactEvent(const ContactEvent& event);
 		void _reportContactEvent(const ContactEvent& event);
 		void _reportTriggerEvent(const TriggerEvent& event);
 		void _reportTriggerEvent(const TriggerEvent& event);
 		void _reportJointBreakEvent(const JointBreakEvent& event);
 		void _reportJointBreakEvent(const JointBreakEvent& event);

+ 6 - 0
BansheePhysX/Source/BsPhysX.cpp

@@ -532,6 +532,12 @@ namespace BansheeEngine
 		return bs_shared_ptr_new<PhysXMeshCollider>(mPhysics, position, rotation);
 		return bs_shared_ptr_new<PhysXMeshCollider>(mPhysics, position, rotation);
 	}
 	}
 
 
+	SPtr<CharacterController> PhysX::createCharacterController()
+	{
+		// TODO - Not implemented
+		return nullptr;
+	}
+
 	SPtr<FixedJoint> PhysX::createFixedJoint()
 	SPtr<FixedJoint> PhysX::createFixedJoint()
 	{
 	{
 		return bs_shared_ptr_new<PhysXFixedJoint>(mPhysics);
 		return bs_shared_ptr_new<PhysXFixedJoint>(mPhysics);

+ 1 - 0
BansheeUtility/BansheeUtility.vcxproj

@@ -320,6 +320,7 @@
     <ClInclude Include="Include\BsCrashHandler.h" />
     <ClInclude Include="Include\BsCrashHandler.h" />
     <ClInclude Include="Include\BsDebug.h" />
     <ClInclude Include="Include\BsDebug.h" />
     <ClInclude Include="Include\BsEvent.h" />
     <ClInclude Include="Include\BsEvent.h" />
+    <ClInclude Include="Include\BsFlags.h" />
     <ClInclude Include="Include\BsLineSegment3.h" />
     <ClInclude Include="Include\BsLineSegment3.h" />
     <ClInclude Include="Include\BsLog.h" />
     <ClInclude Include="Include\BsLog.h" />
     <ClInclude Include="Include\BsMatrixNxM.h" />
     <ClInclude Include="Include\BsMatrixNxM.h" />

+ 3 - 0
BansheeUtility/BansheeUtility.vcxproj.filters

@@ -362,6 +362,9 @@
     <ClInclude Include="Include\Win32\BsWin32Window.h">
     <ClInclude Include="Include\Win32\BsWin32Window.h">
       <Filter>Header Files\Win32</Filter>
       <Filter>Header Files\Win32</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsFlags.h">
+      <Filter>Header Files\General</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsAsyncOp.cpp">
     <ClCompile Include="Source\BsAsyncOp.cpp">

+ 233 - 0
BansheeUtility/Include/BsFlags.h

@@ -0,0 +1,233 @@
+//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
+//**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
+#pragma once
+
+namespace BansheeEngine
+{
+	/** @addtogroup General
+	 *  @{
+	 */
+
+	/** Wrapper around an enum that allows simple use of bitwise logic operations. */
+	template<typename Enum, typename Storage = UINT32>
+	class Flags
+	{
+	public:
+		typedef Storage InternalType;
+
+		Flags()
+			:mBits(0)
+		{ }
+					
+		Flags(Enum value)
+		{
+			mBits = static_cast<Storage>(value);
+		}
+
+		Flags(const Flags<Enum, Storage>& value)
+		{
+			mBits = value.mBits;
+		}
+
+		explicit Flags(Storage bits)
+		{
+			mBits = bits;
+		}
+
+		/** Checks whether all of the provided bits are set */
+		bool isSet(Enum value) const
+		{
+			return (mBits & static_cast<Storage>(value)) == static_cast<Storage>(value);
+		}
+
+		/** Activates all of the provided bits. */
+		Flags<Enum, Storage>& set(Enum value)
+		{
+			mBits = static_cast<Storage>(value);
+
+			return *this;
+		}
+
+		/** Deactivates all of the provided bits. */
+		void unset(Enum value)
+		{
+			mBits &= ~static_cast<Storage>(value);
+		}
+
+		bool operator==(Enum rhs) const
+		{
+			return mBits == static_cast<Storage>(rhs);
+		}
+
+		bool operator==(const Flags<Enum, Storage>& rhs) const
+		{
+			return mBits == rhs.mBits;
+		}
+
+		bool operator==(bool rhs) const
+		{
+			return ((bool)*this) == rhs;
+		}
+
+		bool operator!=(Enum rhs) const
+		{
+			return mBits != static_cast<Storage>(rhs);
+		}
+
+		bool operator!=(const Flags<Enum, Storage>& rhs) const
+		{
+			return mBits != rhs.mBits;
+		}
+
+		Flags<Enum, Storage>& operator= (Enum rhs)
+		{
+			mBits = static_cast<Storage>(rhs);
+
+			return *this;
+		}
+
+		Flags<Enum, Storage>& operator= (const Flags<Enum, Storage>& rhs)
+		{
+			mBits = rhs.mBits;
+
+			return *this;
+		}
+
+		Flags<Enum, Storage>& operator|= (Enum rhs)
+		{
+			mBits |= static_cast<Storage>(rhs);
+
+			return *this;
+		}
+
+		Flags<Enum, Storage>& operator|= (const Flags<Enum, Storage>& rhs)
+		{
+			mBits |= rhs.mBits;
+
+			return *this;
+		}
+
+		Flags<Enum, Storage> operator| (Enum rhs) const
+		{
+			Flags<Enum, Storage> out(*this);
+			out |= rhs;
+
+			return out;
+		}
+
+		Flags<Enum, Storage> operator| (const Flags<Enum, Storage>& rhs) const
+		{
+			Flags<Enum, Storage> out(*this);
+			out |= rhs;
+
+			return out;
+		}
+
+		Flags<Enum, Storage>& operator&= (Enum rhs)
+		{
+			mBits &= static_cast<Storage>(rhs);
+
+			return *this;
+		}
+
+		Flags<Enum, Storage>& operator&= (const Flags<Enum, Storage>& rhs)
+		{
+			mBits &= rhs.mBits;
+
+			return *this;
+		}
+
+		Flags<Enum, Storage> operator& (Enum rhs) const
+		{
+			Flags<Enum, Storage> out = *this;
+			out.mBits &= static_cast<Storage>(rhs);
+
+			return out;
+		}
+
+		Flags<Enum, Storage> operator& (const Flags<Enum, Storage>& rhs) const
+		{
+			Flags<Enum, Storage> out = *this;
+			out.mBits &= rhs.mBits;
+
+			return out;
+		}
+
+		Flags<Enum, Storage>& operator^= (Enum rhs)
+		{
+			mBits ^= static_cast<Storage>(rhs);
+
+			return *this;
+		}
+
+		Flags<Enum, Storage>& operator^= (const Flags<Enum, Storage>& rhs)
+		{
+			mBits ^= f.mBits;
+
+			return *this;
+		}
+
+		Flags<Enum, Storage> operator^ (Enum rhs) const
+		{
+			Flags<Enum, Storage> out = *this;
+			out.mBits ^= static_cast<Storage>(rhs);
+
+			return out;
+		}
+
+		Flags<Enum, Storage> operator^ (const Flags<Enum, Storage>& rhs) const
+		{
+			Flags<Enum, Storage> out = *this;
+			out.mBits ^= rhs.mBits;
+
+			return out;
+		}
+
+		Flags<Enum, Storage> operator~ () const
+		{
+			Flags<Enum, Storage> out;
+			out.mBits = (Storage)~mBits;
+
+			return out;
+		}
+
+		operator bool() const
+		{
+			return mBits ? true : false;
+		}
+
+		operator UINT8() const
+		{
+			return static_cast<UINT8>(mBits);
+		}
+
+		operator UINT16() const
+		{
+			return static_cast<UINT16>(mBits);
+		}
+
+		operator UINT32() const
+		{
+			return static_cast<UINT32>(mBits);
+		}
+
+		friend Flags<Enum, Storage> operator&(Enum a, Flags<Enum, Storage> &b)
+		{
+			Flags<Enum, Storage> out;
+			out.mBits = a & b.mBits;
+			return out;
+		}
+
+	private:
+		Storage mBits;
+	};
+
+#define BS_FLAGS_OPERATORS(Enum) BS_FLAGS_OPERATORS_EXT(Enum, UINT32)
+
+#define BS_FLAGS_OPERATORS_EXT(Enum, Storage)                                                            \
+		Flags<Enum, Storage> operator|(Enum a, Enum b) { Flags<Enum, Storage> r(a); r |= b; return r; } \
+		Flags<Enum, Storage> operator&(Enum a, Enum b) { Flags<Enum, Storage> r(a); r &= b; return r; } \
+		Flags<Enum, Storage> operator~(Enum a) { return ~Flags<Enum, Storage>(a); }
+
+	 /** @} */
+}

+ 1 - 0
BansheeUtility/Include/BsPrerequisitesUtil.h

@@ -173,6 +173,7 @@
 
 
 #include "BsRTTIPrerequisites.h"
 #include "BsRTTIPrerequisites.h"
 
 
+#include "BsFlags.h"
 #include "BsString.h"
 #include "BsString.h"
 #include "BsMessageHandlerFwd.h"
 #include "BsMessageHandlerFwd.h"
 #include "BsUtil.h"
 #include "BsUtil.h"