Skip to content

Commit 72330cf

Browse files
committed
CharacterController[3]
1 parent 674779d commit 72330cf

3 files changed

Lines changed: 75 additions & 8 deletions

File tree

3DRadSpace/Engine3DRadSpace/Physics/ICharacterController.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Engine3DRadSpace::Physics
1717
virtual void _setRadius(float radius) = 0;
1818
virtual float _getRadius() const noexcept = 0;
1919

20-
float _maxSlopeAngle;
20+
float _maxSlopeAngle = std::numbers::pi_v<float> / 4.0f;
2121
virtual void _setMaxSlopeAngle(float angle) = 0;
2222
virtual float _getMaxSlopeAngle() const noexcept = 0;
2323

3DRadSpace/Engine3DRadSpace/Physics/NVPhysX/CharacterController.cpp

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
#include "CharacterController.hpp"
2+
#include "../../Logging/Exception.hpp"
23
#include <characterkinematic/PxControllerManager.h>
34
#include <characterkinematic/PxController.h>
45
#include <characterkinematic/PxCapsuleController.h>
56
#include <PxPhysics.h>
67
#include <PxScene.h>
8+
#include <PxRigidDynamic.h>
9+
#include <PxMaterial.h>
10+
#include <geometry/PxGeometryQuery.h>
711

812
using namespace Engine3DRadSpace;
913
using namespace Engine3DRadSpace::Math;
@@ -26,9 +30,15 @@ CharacterController::CharacterController(
2630
desc.setToDefault();
2731
desc.height = height;
2832
desc.radius = radius;
29-
desc.slopeLimit = 0.707f; // 45 deg
33+
desc.slopeLimit = std::cos(_maxSlopeAngle);
34+
desc.material = nvPhysics->createMaterial(0.5f, 0.5f, 0.0f);
35+
_material = PxUPtr<physx::PxMaterial>(desc.material);
3036

3137
auto controller = nvControllerManager->createController(desc);
38+
if(controller == nullptr)
39+
{
40+
throw Logging::Exception("CharacterController creation failed!");
41+
}
3242
_controller.reset(static_cast<physx::PxCapsuleController*>(controller));
3343

3444
auto scene = static_cast<physx::PxScene*>(physics->GetScene());
@@ -96,7 +106,7 @@ void CharacterController::Move(const Math::Vector3& displacement)
96106

97107
_verticalVelocity += Gravity.Get() * dt;
98108

99-
if(IsGrounded() && _verticalVelocity.Y <= 0.0f)
109+
if(IsGrounded() && Vector3::Dot(_verticalVelocity, _gravity) >= 0.0f)
100110
_verticalVelocity = Vector3::Zero();
101111

102112
physx::PxVec3 motion =
@@ -105,18 +115,22 @@ void CharacterController::Move(const Math::Vector3& displacement)
105115
_controller->move(
106116
motion,
107117
0.001f,
108-
_physics->dt(),
118+
dt,
109119
physx::PxControllerFilters(),
110120
nullptr
111121
);
112122
}
113123

114124
void CharacterController::Jump(float height)
115125
{
116-
if(!IsGrounded()) return;
126+
if(!IsGrounded() || height <= 0.0f) return;
117127

118128
float g = _gravity.Length();
119-
_verticalVelocity = Vector3(0, std::sqrt(2.0f * g * height), 0);
129+
if(g == 0.0f) return;
130+
131+
// Conservation of energy: (1/2)m(v^2) = mgh -> v = sqrt(2gh)
132+
float speed = std::sqrt(2.0f * g * height);
133+
_verticalVelocity = Vector3::Normalize(-_gravity) * speed;
120134
}
121135

122136
bool CharacterController::IsGrounded()
@@ -126,6 +140,11 @@ bool CharacterController::IsGrounded()
126140
physx::PxControllerState state;
127141
_controller->getState(state);
128142

143+
if((state.collisionFlags & physx::PxControllerCollisionFlag::eCOLLISION_UP) != 0)
144+
{
145+
_verticalVelocity = Vector3::Zero();
146+
}
147+
129148
return (state.collisionFlags & physx::PxControllerCollisionFlag::eCOLLISION_DOWN) != 0;
130149
}
131150

@@ -139,12 +158,51 @@ float CharacterController::_getMass()
139158

140159
void CharacterController::_setMass(float mass)
141160
{
142-
// Do nothing, character controller doesn't have mass
161+
(void)mass;
143162
}
144163

145164
std::optional<float> CharacterController::Intersects(const Math::Ray& r)
146165
{
147-
return std::nullopt;
166+
if(_controller == nullptr) return std::nullopt;
167+
168+
physx::PxVec3 origin(r.Origin.X, r.Origin.Y, r.Origin.Z);
169+
physx::PxVec3 dir(r.Direction.X, r.Direction.Y, r.Direction.Z);
170+
171+
if(dir.normalize() == 0.0f) return std::nullopt;
172+
173+
auto numShapes = _controller->getActor()->getNbShapes();
174+
if(numShapes == 0) return std::nullopt;
175+
176+
std::vector<physx::PxShape*> shapes(numShapes);
177+
auto rigidbody = _controller->getActor();
178+
rigidbody->getShapes(shapes.data(), numShapes);
179+
180+
float closestDist = PX_MAX_F32;
181+
bool hasHit = false;
182+
183+
for(auto* shape : shapes)
184+
{
185+
physx::PxTransform pose = rigidbody->getGlobalPose() * shape->getLocalPose();
186+
physx::PxRaycastHit hit;
187+
188+
physx::PxU32 hitCount = physx::PxGeometryQuery::raycast(
189+
origin, dir,
190+
shape->getGeometry(),
191+
pose,
192+
PX_MAX_F32,
193+
physx::PxHitFlag::eDEFAULT,
194+
1,
195+
&hit
196+
);
197+
198+
if(hitCount > 0 && hit.distance < closestDist)
199+
{
200+
closestDist = hit.distance;
201+
hasHit = true;
202+
}
203+
}
204+
205+
return hasHit ? std::optional<float>(closestDist) : std::nullopt;
148206
}
149207

150208
void CharacterController::UpdateTransform()
@@ -159,4 +217,12 @@ void CharacterController::UpdateTransform(const Math::Vector3& position, const M
159217
{
160218
if(!_controller) return;
161219
_controller->setPosition(physx::PxExtendedVec3(position.X, position.Y, position.Z));
220+
221+
Vector3 up = Vector3::Transform(Vector3::Up(), rotation);
222+
_controller->setUpDirection(physx::PxVec3(up.X, up.Y, up.Z));
223+
}
224+
225+
Math::Vector3 CharacterController::GetPosition() const noexcept
226+
{
227+
return _position;
162228
}

3DRadSpace/Engine3DRadSpace/Physics/NVPhysX/CharacterController.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace Engine3DRadSpace::Physics::NVPhysX
2020
Math::Vector3 _getGravity() const noexcept override;
2121
void _setGravity(const Math::Vector3& gravity) override;
2222

23+
PxUPtr<physx::PxMaterial> _material;
2324
PxUPtr<physx::PxCapsuleController> _controller;
2425
Math::Vector3 _verticalVelocity = Math::Vector3::Zero();
2526

0 commit comments

Comments
 (0)