mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-15 20:08:54 +03:00
Added better character auto stepping and component settings
This commit is contained in:
@@ -45,6 +45,7 @@ class Scene {
|
||||
// Transform
|
||||
|
||||
foreign static GetScript_(e)
|
||||
foreign static GetLocalTranslation_(e)
|
||||
foreign static GetTranslation_(e)
|
||||
foreign static SetTranslation_(e, x, y, z)
|
||||
foreign static SetRotation_(e, x, y, z)
|
||||
@@ -123,11 +124,17 @@ class TransformComponent {
|
||||
_entityId = id
|
||||
}
|
||||
|
||||
GetLocalTranslation() {
|
||||
var result = Scene.GetLocalTranslation_(_entityId)
|
||||
return Vector3.new(result[0], result[1], result[2])
|
||||
}
|
||||
|
||||
GetTranslation() {
|
||||
var result = Scene.GetTranslation_(_entityId)
|
||||
return Vector3.new(result[0], result[1], result[2])
|
||||
}
|
||||
|
||||
|
||||
SetTranslation(t) {
|
||||
Scene.SetTranslation_(_entityId, t.x, t.y, t.z)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
{
|
||||
if (!entity.HasComponent<Nuake::CharacterControllerComponent>())
|
||||
return;
|
||||
using namespace Nuake;
|
||||
|
||||
auto& component = entity.GetComponent<Nuake::CharacterControllerComponent>();
|
||||
BeginComponentTable(CHARACTER CONTROLLER, Nuake::CharacterControllerComponent);
|
||||
@@ -33,6 +34,59 @@ public:
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.MaxSlopeAngle, 0.45f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Auto stepping");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##AutoStepping", &component.AutoStepping);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.AutoStepping, true)
|
||||
}
|
||||
|
||||
if (component.AutoStepping)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Stick to floor step down");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##StickToFloorStepDown", &component.StickToFloorStepDown.y, -10.0f, 0.01, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.StickToFloorStepDown.y, -0.5f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Step down extra");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##StepDownExtra", &component.StepDownExtra.y, -10.0f, 0.01, 0.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.StepDownExtra.y, 0.0f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Step up");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##StepUp", &component.SteppingStepUp.y, 0.0f, 0.01, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.SteppingStepUp.y, 0.4f);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Step distance");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##StepDistance", &component.SteppingForwardDistance, 0.0f, 0.01f, 10.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.SteppingForwardDistance, 0.250f)
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
ImGui::Text("Step min distance");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::DragFloat("##StepMinDistance", &component.SteppingMinDistance, 0.0f, 0.01f, component.SteppingForwardDistance);
|
||||
ImGui::TableNextColumn();
|
||||
ComponentTableReset(component.SteppingMinDistance, 0.125f)
|
||||
}
|
||||
}
|
||||
}
|
||||
EndComponentTable()
|
||||
}
|
||||
|
||||
@@ -8,11 +8,17 @@ namespace Nuake
|
||||
{
|
||||
namespace Physics
|
||||
{
|
||||
CharacterController::CharacterController(const Ref<PhysicShape>& shape, float friction, float maxSlopeAngle)
|
||||
CharacterController::CharacterController(const CharacterControllerSettings& settings)
|
||||
{
|
||||
Shape = shape;
|
||||
Friction = friction;
|
||||
MaxSlopeAngle = maxSlopeAngle;
|
||||
Shape = settings.Shape;
|
||||
Friction = settings.Friction;
|
||||
MaxSlopeAngle = settings.MaxSlopeAngle;
|
||||
AutoStepping = settings.AutoStepping;
|
||||
StepDown = settings.StepDown;
|
||||
StepDownExtra = settings.StepDownExtra;
|
||||
StepUp = settings.StepUp;
|
||||
StepDistance = settings.StepDistance;
|
||||
StepMinDistance = settings.StepMinDistance;
|
||||
}
|
||||
|
||||
void CharacterController::SetEntity(Entity& ent)
|
||||
|
||||
@@ -10,35 +10,49 @@ namespace Nuake
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
struct CharacterControllerSettings
|
||||
{
|
||||
Ref<Physics::PhysicShape> Shape;
|
||||
float Friction;
|
||||
float MaxSlopeAngle;
|
||||
bool AutoStepping;
|
||||
Vector3 StepDown;
|
||||
Vector3 StepDownExtra;
|
||||
Vector3 StepUp;
|
||||
float StepMinDistance;
|
||||
float StepDistance;
|
||||
};
|
||||
|
||||
class CharacterController
|
||||
{
|
||||
public:
|
||||
Vector3 Position = Vector3(0, 0, 0);
|
||||
Quat Rotation = Quat(1, 0, 0, 0);
|
||||
|
||||
Entity Owner;
|
||||
|
||||
bool IsOnGround = false;
|
||||
bool m_hittingWall;
|
||||
|
||||
float m_stepHeight = 0.35f;
|
||||
float MaxSlopeAngle = 45.0f;
|
||||
float Friction = 0.5f;
|
||||
// Settings
|
||||
Ref<PhysicShape> Shape;
|
||||
float Friction = 0.5f;
|
||||
float MaxSlopeAngle = 45.0f;
|
||||
bool AutoStepping;
|
||||
Vector3 StepDown;
|
||||
Vector3 StepDownExtra;
|
||||
Vector3 StepUp;
|
||||
float StepDistance;
|
||||
float StepMinDistance;
|
||||
|
||||
float m_bottomYOffset;
|
||||
float m_bottomRoundedRegionYOffset;
|
||||
// State
|
||||
Vector3 Position = Vector3(0, 0, 0);
|
||||
Quat Rotation = Quat(1, 0, 0, 0);
|
||||
bool IsOnGround = false;
|
||||
|
||||
Vector3 m_manualVelocity;
|
||||
std::vector<Vector3> m_surfaceHitNormals;
|
||||
public:
|
||||
CharacterController(const CharacterControllerSettings& settings);
|
||||
|
||||
CharacterController(const Ref<PhysicShape>& shape, float friction, float maxSlopeAngle);
|
||||
void MoveAndSlide(const Vector3& velocity);
|
||||
|
||||
void SetEntity(Entity& ent);
|
||||
Entity GetEntity() const;
|
||||
void MoveAndSlide(const Vector3& velocity);
|
||||
|
||||
bool IsOnFloor()
|
||||
bool IsOnFloor() const
|
||||
{
|
||||
return IsOnGround;
|
||||
}
|
||||
|
||||
@@ -331,29 +331,18 @@ namespace Nuake
|
||||
void DynamicWorld::AddCharacterController(Ref<CharacterController> cc)
|
||||
{
|
||||
JPH::Ref<JPH::CharacterVirtualSettings> settings = new JPH::CharacterVirtualSettings();
|
||||
//settings->mMaxSlopeAngle = JPH::DegreesToRadians(cc->MaxSlopeAngle);
|
||||
//settings->mLayer = Layers::MOVING;
|
||||
//settings->mFriction = cc->Friction;
|
||||
//settings->mShape = GetJoltShape(cc->Shape);
|
||||
//settings->mGravityFactor = 0.0f;
|
||||
settings->mSupportingVolume = JPH::Plane(JPH::Vec3::sAxisY(), -0.5f);
|
||||
settings->mMaxSlopeAngle = JPH::DegreesToRadians(cc->MaxSlopeAngle);
|
||||
settings->mMaxStrength = 10.0;
|
||||
settings->mCharacterPadding = 0.01f;
|
||||
settings->mMaxStrength = 1.0f;
|
||||
settings->mCharacterPadding = 0.05f;
|
||||
settings->mPenetrationRecoverySpeed = 1.0f;
|
||||
settings->mPredictiveContactDistance = 0.01f;
|
||||
settings->mShape = GetJoltShape(cc->Shape);
|
||||
|
||||
auto& joltPosition = JPH::Vec3(cc->Position.x, cc->Position.y, cc->Position.z);
|
||||
|
||||
Quat& bodyRotation = cc->Rotation;
|
||||
|
||||
// We need to add 180 degrees because our forward is -Z.
|
||||
const auto& yOffset = Vector3(0.0f, Rad(180.0), 0.0f);
|
||||
//bodyRotation = glm::normalize(bodyRotation * Quat(yOffset));
|
||||
|
||||
const Quat& bodyRotation = cc->Rotation;
|
||||
const auto& joltRotation = JPH::Quat(bodyRotation.x, bodyRotation.y, bodyRotation.z, bodyRotation.w);
|
||||
JPH::CharacterVirtual* character = new JPH::CharacterVirtual(settings, joltPosition, joltRotation, _JoltPhysicsSystem.get());
|
||||
auto character = new JPH::CharacterVirtual(settings, std::move(joltPosition), std::move(joltRotation), _JoltPhysicsSystem.get());
|
||||
|
||||
//character->AddToPhysicsSystem(JPH::EActivation::Activate);
|
||||
|
||||
@@ -514,36 +503,49 @@ namespace Nuake
|
||||
try
|
||||
{
|
||||
// TODO: Potential memory leak with new keyword.
|
||||
auto joltTempAllocator = CreateRef<JPH::TempAllocatorMalloc>();
|
||||
|
||||
JPH::CharacterVirtual::ExtendedUpdateSettings update_settings;
|
||||
update_settings.mStickToFloorStepDown = -JPH::Vec3(0, 1, 0) * update_settings.mStickToFloorStepDown.Length();
|
||||
update_settings.mWalkStairsStepUp = JPH::Vec3(0, 1, 0) * update_settings.mWalkStairsStepUp.Length();
|
||||
update_settings.mWalkStairsMinStepForward = 0.10;
|
||||
update_settings.mWalkStairsStepForwardTest = 0.15f;
|
||||
JPH::CharacterVirtual::ExtendedUpdateSettings joltUpdateSettings;
|
||||
|
||||
for (auto& c : _registeredCharacters)
|
||||
{
|
||||
//c.second->PostSimulation(0.05f);
|
||||
Entity entity{ (entt::entity)c.first, Engine::GetCurrentScene().get() };
|
||||
|
||||
c.second->ExtendedUpdate(ts,
|
||||
-JPH::Vec3(0, 0, 0) * _JoltPhysicsSystem->GetGravity().Length(),
|
||||
update_settings,
|
||||
_JoltPhysicsSystem->GetDefaultBroadPhaseLayerFilter(Layers::MOVING),
|
||||
_JoltPhysicsSystem->GetDefaultLayerFilter(Layers::MOVING),
|
||||
{ },
|
||||
{ },
|
||||
*(new JPH::TempAllocatorMalloc()));
|
||||
if (entity.HasComponent<CharacterControllerComponent>())
|
||||
{
|
||||
auto& characterControllerComponent = entity.GetComponent<CharacterControllerComponent>();
|
||||
auto characterController = characterControllerComponent.GetCharacterController();
|
||||
|
||||
const auto& broadPhaseLayerFilter = _JoltPhysicsSystem->GetDefaultBroadPhaseLayerFilter(Layers::MOVING);
|
||||
const auto& LayerFilter = _JoltPhysicsSystem->GetDefaultLayerFilter(Layers::MOVING);
|
||||
const auto& joltGravity = _JoltPhysicsSystem->GetGravity();
|
||||
auto& tempAllocatorPtr = *(joltTempAllocator);
|
||||
if (characterController->AutoStepping)
|
||||
{
|
||||
// Create update settings from character controller
|
||||
joltUpdateSettings.mStickToFloorStepDown = CreateJoltVec3(characterController->StepDown);
|
||||
joltUpdateSettings.mWalkStairsStepDownExtra = CreateJoltVec3(characterController->StepDownExtra);
|
||||
joltUpdateSettings.mWalkStairsStepUp = CreateJoltVec3(characterController->StepUp);
|
||||
joltUpdateSettings.mWalkStairsStepForwardTest = characterController->StepDistance;
|
||||
joltUpdateSettings.mWalkStairsMinStepForward = characterController->StepMinDistance;
|
||||
|
||||
c.second->ExtendedUpdate(ts, joltGravity, joltUpdateSettings, broadPhaseLayerFilter, LayerFilter, { }, { }, tempAllocatorPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.second->Update(ts, joltGravity, broadPhaseLayerFilter, LayerFilter, {}, {}, tempAllocatorPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_JoltPhysicsSystem->Update(ts, collisionSteps, new JPH::TempAllocatorMalloc(), _JoltJobSystem);
|
||||
|
||||
_JoltPhysicsSystem->Update(ts, collisionSteps, joltTempAllocator.get(), _JoltJobSystem);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::Log("Failed to run simulation update", "physics", CRITICAL);
|
||||
}
|
||||
|
||||
|
||||
SyncEntitiesTranforms();
|
||||
SyncCharactersTransforms();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
|
||||
namespace JPH
|
||||
{
|
||||
class PhysicsSystem;
|
||||
@@ -26,14 +27,13 @@ namespace JPH
|
||||
class Ref;
|
||||
}
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class BPLayerInterfaceImpl;
|
||||
class MyContactListener;
|
||||
class MyBodyActivationListener;
|
||||
|
||||
namespace Physics
|
||||
namespace Physics
|
||||
{
|
||||
class DynamicWorld
|
||||
{
|
||||
@@ -73,6 +73,11 @@ namespace Nuake
|
||||
JPH::Ref<JPH::Shape> GetJoltShape(const Ref<PhysicShape> shape);
|
||||
void SyncEntitiesTranforms();
|
||||
void SyncCharactersTransforms();
|
||||
|
||||
JPH::Vec3 CreateJoltVec3(const Vector3& input) const
|
||||
{
|
||||
return JPH::Vec3(input.x, input.y, input.z);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,12 @@ using json = nlohmann::json;
|
||||
SERIALIZE_VEC3(v) \
|
||||
j[#v]["w"] = this->v.w;
|
||||
|
||||
#define DESERIALIZE_VAL(p) \
|
||||
if(j.contains(#p)) \
|
||||
{ \
|
||||
p = j[#p]; \
|
||||
}
|
||||
|
||||
#define DESERIALIZE_VEC4(v, p) \
|
||||
p = Vector4(v["x"], v["y"], v["z"], v["w"]);
|
||||
|
||||
|
||||
@@ -1,40 +1,83 @@
|
||||
#pragma once
|
||||
#include "src/Core/Physics/CharacterController.h"
|
||||
|
||||
namespace Nuake {
|
||||
namespace Nuake
|
||||
{
|
||||
class CharacterControllerComponent
|
||||
{
|
||||
public:
|
||||
Ref<Physics::CharacterController> CharacterController;
|
||||
private:
|
||||
Ref<Physics::CharacterController> m_CharacterController;
|
||||
|
||||
public:
|
||||
// Auto stepping settings
|
||||
bool AutoStepping = false;
|
||||
Vector3 StickToFloorStepDown = Vector3(0.f, -0.5f, 0.f);
|
||||
Vector3 StepDownExtra = Vector3(0, 0, 0); // ??
|
||||
Vector3 SteppingStepUp = Vector3(0.f, 0.4f, 0.f);
|
||||
float SteppingMinDistance = 0.125f;
|
||||
float SteppingForwardDistance = 0.250f;
|
||||
|
||||
float Friction = 0.5f;
|
||||
float MaxSlopeAngle = 0.45f;
|
||||
float MaxSlopeAngle = 45.0f;
|
||||
float MaxStrength = 1.0f;
|
||||
|
||||
CharacterControllerComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void SetCharacterController(const Ref<Physics::CharacterController>& charController)
|
||||
{
|
||||
m_CharacterController = charController;
|
||||
}
|
||||
|
||||
Ref<Physics::CharacterController> GetCharacterController() const
|
||||
{
|
||||
return m_CharacterController;
|
||||
}
|
||||
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_VAL(AutoStepping);
|
||||
SERIALIZE_VEC3(StickToFloorStepDown);
|
||||
SERIALIZE_VEC3(StepDownExtra);
|
||||
SERIALIZE_VEC3(SteppingStepUp);
|
||||
SERIALIZE_VAL(SteppingMinDistance);
|
||||
SERIALIZE_VAL(SteppingForwardDistance);
|
||||
|
||||
SERIALIZE_VAL(Friction);
|
||||
SERIALIZE_VAL(MaxSlopeAngle);
|
||||
SERIALIZE_VAL(MaxStrength);
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
if (j.contains("Friction"))
|
||||
{
|
||||
Friction = j["Friction"];
|
||||
}
|
||||
DESERIALIZE_VAL(AutoStepping);
|
||||
DESERIALIZE_VAL(Friction);
|
||||
DESERIALIZE_VAL(MaxSlopeAngle);
|
||||
|
||||
if (j.contains("MaxSlopeAngle"))
|
||||
if (j.contains("StickToFloorStepDown"))
|
||||
{
|
||||
MaxSlopeAngle = j["MaxSlopeAngle"];
|
||||
DESERIALIZE_VEC3(j["StickToFloorStepDown"], StickToFloorStepDown);
|
||||
}
|
||||
|
||||
if (j.contains("StepDownExtra"))
|
||||
{
|
||||
DESERIALIZE_VEC3(j["StepDownExtra"], StepDownExtra);
|
||||
}
|
||||
|
||||
if (j.contains("SteppingStepUp"))
|
||||
{
|
||||
DESERIALIZE_VEC3(j["SteppingStepUp"], SteppingStepUp);
|
||||
}
|
||||
|
||||
DESERIALIZE_VAL(SteppingMinDistance);
|
||||
DESERIALIZE_VAL(SteppingForwardDistance);
|
||||
|
||||
DESERIALIZE_VAL(Friction);
|
||||
DESERIALIZE_VAL(MaxSlopeAngle);
|
||||
DESERIALIZE_VAL(MaxStrength);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -327,15 +327,25 @@ namespace Nuake
|
||||
shape = capsuleColliderComponent.Box;
|
||||
}
|
||||
|
||||
const float friction = characterControllerComponent.Friction;
|
||||
const float maxSlopeAngle = characterControllerComponent.MaxSlopeAngle;
|
||||
auto characterController = CreateRef<Physics::CharacterController>(shape, friction, maxSlopeAngle);
|
||||
Physics::CharacterControllerSettings settings
|
||||
{
|
||||
shape,
|
||||
characterControllerComponent.Friction,
|
||||
characterControllerComponent.MaxSlopeAngle,
|
||||
characterControllerComponent.AutoStepping,
|
||||
characterControllerComponent.StickToFloorStepDown,
|
||||
characterControllerComponent.StepDownExtra,
|
||||
characterControllerComponent.SteppingStepUp,
|
||||
characterControllerComponent.SteppingMinDistance,
|
||||
characterControllerComponent.SteppingForwardDistance
|
||||
};
|
||||
|
||||
auto characterController = CreateRef<Physics::CharacterController>(std::move(settings));
|
||||
characterController->SetEntity(entity); // Used to link back to the entity
|
||||
characterController->Position = transformComponent.GetGlobalPosition();
|
||||
characterController->Rotation = transformComponent.GetGlobalRotation();
|
||||
|
||||
characterControllerComponent.CharacterController = characterController;
|
||||
PhysicsManager::Get().RegisterCharacterController(characterControllerComponent.CharacterController);
|
||||
characterControllerComponent.SetCharacterController(characterController);
|
||||
PhysicsManager::Get().RegisterCharacterController(characterController);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Nuake
|
||||
RegisterMethod("EntityHasComponent(_,_)", (void*)EntityHasComponent);
|
||||
|
||||
RegisterMethod("GetTranslation_(_)", (void*)GetTranslation);
|
||||
RegisterMethod("GetLocalTranslation_(_)", (void*)GetLocalTranslation);
|
||||
RegisterMethod("SetTranslation_(_,_,_,_)", (void*)SetTranslation);
|
||||
RegisterMethod("GetRotation_(_)", (void*)GetRotation);
|
||||
RegisterMethod("SetRotation_(_,_,_,_)", (void*)SetRotation);
|
||||
@@ -290,7 +291,7 @@ namespace Nuake
|
||||
|
||||
Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get());
|
||||
auto& characterController = ent.GetComponent<CharacterControllerComponent>();
|
||||
characterController.CharacterController->MoveAndSlide(Vector3(x, y, z));
|
||||
characterController.GetCharacterController()->MoveAndSlide(Vector3(x, y, z));
|
||||
}
|
||||
|
||||
static void AddForce(WrenVM* vm)
|
||||
@@ -323,6 +324,24 @@ namespace Nuake
|
||||
wrenInsertInList(vm, 0, 2, 3);
|
||||
}
|
||||
|
||||
static void GetLocalTranslation(WrenVM* vm)
|
||||
{
|
||||
double handle = wrenGetSlotDouble(vm, 1);
|
||||
Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get());
|
||||
auto& transform = ent.GetComponent<TransformComponent>();
|
||||
// set the slots
|
||||
Vector3 position = transform.GetLocalPosition();
|
||||
wrenSetSlotDouble(vm, 1, position.x);
|
||||
wrenSetSlotDouble(vm, 2, position.y);
|
||||
wrenSetSlotDouble(vm, 3, position.z);
|
||||
|
||||
// Fill the list
|
||||
wrenSetSlotNewList(vm, 0);
|
||||
wrenInsertInList(vm, 0, 0, 1);
|
||||
wrenInsertInList(vm, 0, 1, 2);
|
||||
wrenInsertInList(vm, 0, 2, 3);
|
||||
}
|
||||
|
||||
static void GetRotation(WrenVM* vm)
|
||||
{
|
||||
double handle = wrenGetSlotDouble(vm, 1);
|
||||
|
||||
Reference in New Issue
Block a user