mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-09 20:08:57 +03:00
Merge pull request #57 from antopilo/feature/physics-improvements
Feature/physics improvements
This commit is contained in:
Submodule Nuake/dependencies/JoltPhysics updated: 0e4865a345...b767673cd5
@@ -161,7 +161,7 @@ namespace Nuake
|
||||
{
|
||||
public:
|
||||
// See: ContactListener
|
||||
virtual JPH::ValidateResult OnContactValidate(const JPH::Body& inBody1, const JPH::Body& inBody2, const JPH::CollideShapeResult& inCollisionResult) override
|
||||
virtual JPH::ValidateResult OnContactValidate(const JPH::Body& inBody1, const JPH::Body& inBody2, JPH::RVec3Arg inBaseOffset, const JPH::CollideShapeResult& inCollisionResult) override
|
||||
{
|
||||
//std::cout << "Contact validate callback" << std::endl;
|
||||
|
||||
@@ -200,7 +200,47 @@ namespace Nuake
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectVsBroadPhaseLayerFilterImpl : public JPH::ObjectVsBroadPhaseLayerFilter
|
||||
{
|
||||
public:
|
||||
virtual bool ShouldCollide(JPH::ObjectLayer inLayer1, JPH::BroadPhaseLayer inLayer2) const override
|
||||
{
|
||||
switch (inLayer1)
|
||||
{
|
||||
case Layers::NON_MOVING:
|
||||
return inLayer2 == BroadPhaseLayers::MOVING;
|
||||
case Layers::MOVING:
|
||||
return true;
|
||||
default:
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ObjectLayerPairFilterImpl : public JPH::ObjectLayerPairFilter
|
||||
{
|
||||
public:
|
||||
virtual bool ShouldCollide(JPH::ObjectLayer inObject1, JPH::ObjectLayer inObject2) const override
|
||||
{
|
||||
switch (inObject1)
|
||||
{
|
||||
case Layers::NON_MOVING:
|
||||
return inObject2 == Layers::MOVING; // Non moving only collides with moving
|
||||
case Layers::MOVING:
|
||||
return true; // Moving collides with everything
|
||||
default:
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
BPLayerInterfaceImpl JoltBroadphaseLayerInterface = BPLayerInterfaceImpl();
|
||||
ObjectVsBroadPhaseLayerFilterImpl JoltObjectVSBroadphaseLayerFilter = ObjectVsBroadPhaseLayerFilterImpl();
|
||||
ObjectLayerPairFilterImpl JoltObjectVSObjectLayerFilter;
|
||||
|
||||
namespace Physics
|
||||
{
|
||||
DynamicWorld::DynamicWorld() : _stepCount(0)
|
||||
@@ -208,13 +248,13 @@ namespace Nuake
|
||||
_registeredCharacters = std::map<uint32_t, JPH::Character*>();
|
||||
|
||||
// Initialize Jolt Physics
|
||||
const uint32_t MaxBodies = 1024;
|
||||
const uint32_t MaxBodies = 2048;
|
||||
const uint32_t NumBodyMutexes = 0;
|
||||
const uint32_t MaxBodyPairs = 1024;
|
||||
const uint32_t MaxContactConstraints = 1024;
|
||||
|
||||
_JoltPhysicsSystem = CreateRef<JPH::PhysicsSystem>();
|
||||
_JoltPhysicsSystem->Init(MaxBodies, NumBodyMutexes, MaxBodyPairs, MaxContactConstraints, JoltBroadphaseLayerInterface, MyBroadPhaseCanCollide, MyObjectCanCollide);
|
||||
_JoltPhysicsSystem->Init(MaxBodies, NumBodyMutexes, MaxBodyPairs, MaxContactConstraints, JoltBroadphaseLayerInterface, JoltObjectVSBroadphaseLayerFilter, JoltObjectVSObjectLayerFilter);
|
||||
|
||||
// A body activation listener gets notified when bodies activate and go to sleep
|
||||
// Note that this is called from a job so whatever you do here needs to be thread safe.
|
||||
@@ -295,6 +335,7 @@ namespace Nuake
|
||||
settings->mFriction = cc->Friction;
|
||||
settings->mShape = GetJoltShape(cc->Shape);
|
||||
settings->mGravityFactor = 0.0f;
|
||||
settings->mSupportingVolume = JPH::Plane(JPH::Vec3::sAxisY(), -0.5f);
|
||||
|
||||
auto& joltPosition = JPH::Vec3(cc->Position.x, cc->Position.y, cc->Position.z);
|
||||
|
||||
@@ -302,7 +343,7 @@ namespace Nuake
|
||||
|
||||
// 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));
|
||||
//bodyRotation = glm::normalize(bodyRotation * Quat(yOffset));
|
||||
|
||||
const auto& joltRotation = JPH::Quat(bodyRotation.x, bodyRotation.y, bodyRotation.z, bodyRotation.w);
|
||||
JPH::Character* character = new JPH::Character(settings, joltPosition, joltRotation, cc->GetEntity().GetID() , _JoltPhysicsSystem.get());
|
||||
@@ -320,6 +361,7 @@ namespace Nuake
|
||||
{
|
||||
auto& characterController = _registeredCharacters[entityHandle];
|
||||
const auto groundState = characterController->GetGroundState();
|
||||
|
||||
return groundState == JPH::CharacterBase::EGroundState::OnGround;
|
||||
}
|
||||
|
||||
@@ -331,31 +373,37 @@ namespace Nuake
|
||||
{
|
||||
// Create jolt ray
|
||||
const auto& fromJolt = JPH::Vec3(from.x, from.y, from.z);
|
||||
const auto& toJolt = JPH::Vec3(to.x, to.y, to.z);
|
||||
JPH::RayCast ray { fromJolt, toJolt - fromJolt };
|
||||
JPH::AllHitCollisionCollector<JPH::RayCastBodyCollector> collector;
|
||||
_JoltPhysicsSystem->GetBroadPhaseQuery().CastRay(ray, collector);
|
||||
const auto& toDirectionJolt = JPH::Vec3(to.x - from.x, to.y - from.y, to.z - from.z);
|
||||
JPH::RRayCast ray { fromJolt, toDirectionJolt };
|
||||
JPH::AllHitCollisionCollector<JPH::CastRayCollector> collector;
|
||||
|
||||
JPH::RayCastResult result;
|
||||
_JoltPhysicsSystem->GetNarrowPhaseQuery().CastRay(ray, JPH::RayCastSettings(), collector);
|
||||
|
||||
// Fetch results
|
||||
int num_hits = (int)collector.mHits.size();
|
||||
JPH::BroadPhaseCastResult* results = collector.mHits.data();
|
||||
|
||||
// Format result
|
||||
std::vector<RaycastResult> raycastResults;
|
||||
for (int i = 0; i < num_hits; ++i)
|
||||
|
||||
if (collector.HadHit())
|
||||
{
|
||||
const float hitFraction = results[i].mFraction;
|
||||
const JPH::Vec3& hitPosition = ray.GetPointOnRay(results[i].mFraction);
|
||||
int num_hits = (int)collector.mHits.size();
|
||||
JPH::BroadPhaseCastResult* results = collector.mHits.data();
|
||||
|
||||
RaycastResult result
|
||||
// Format result
|
||||
for (int i = 0; i < num_hits; ++i)
|
||||
{
|
||||
Vector3(hitPosition.GetX(), hitPosition.GetY(), hitPosition.GetZ()),
|
||||
hitFraction
|
||||
};
|
||||
const float hitFraction = results[i].mFraction;
|
||||
const JPH::Vec3& hitPosition = ray.GetPointOnRay(results[i].mFraction);
|
||||
|
||||
raycastResults.push_back(std::move(result));
|
||||
RaycastResult result
|
||||
{
|
||||
Vector3(hitPosition.GetX(), hitPosition.GetY(), hitPosition.GetZ()),
|
||||
hitFraction
|
||||
};
|
||||
|
||||
raycastResults.push_back(std::move(result));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return raycastResults;
|
||||
}
|
||||
|
||||
@@ -435,31 +483,34 @@ namespace Nuake
|
||||
// Next step
|
||||
++_stepCount;
|
||||
|
||||
|
||||
// If you take larger steps than 1 / 60th of a second you need to do multiple collision steps in order to keep the simulation stable.
|
||||
// Do 1 collision step per 1 / 60th of a second (round up).
|
||||
int collisionSteps = 1;
|
||||
constexpr float minStepDuration = 1.0f / 90.0f;
|
||||
constexpr float minStepDuration = 1.0f / 30.0f;
|
||||
constexpr int maxStepCount = 32;
|
||||
|
||||
if(ts > minStepDuration)
|
||||
{
|
||||
Logger::Log("Large step detected: " + std::to_string(ts), "physics", WARNING);
|
||||
collisionSteps = static_cast<float>(ts) / minStepDuration;
|
||||
}
|
||||
|
||||
if (collisionSteps >= maxStepCount)
|
||||
{
|
||||
Logger::Log("Very large step detected: " + std::to_string(ts), "physics", WARNING);
|
||||
}
|
||||
|
||||
// Prevents having too many steps and running out of jobs
|
||||
collisionSteps = std::min(collisionSteps, maxStepCount);
|
||||
|
||||
// If you want more accurate step results you can do multiple sub steps within a collision step. Usually you would set this to 1.
|
||||
constexpr int subSteps = 1;
|
||||
|
||||
// Step the world
|
||||
try
|
||||
{
|
||||
_JoltPhysicsSystem->Update(ts, collisionSteps, subSteps, new JPH::TempAllocatorMalloc(), _JoltJobSystem);
|
||||
_JoltPhysicsSystem->Update(ts, collisionSteps, new JPH::TempAllocatorMalloc(), _JoltJobSystem);
|
||||
|
||||
for (auto& c : _registeredCharacters)
|
||||
{
|
||||
c.second->PostSimulation(0.001);
|
||||
c.second->PostSimulation(0.05f);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
@@ -483,8 +534,6 @@ namespace Nuake
|
||||
_registeredBodies.clear();
|
||||
}
|
||||
|
||||
_registeredBodies.clear();
|
||||
|
||||
if (!_registeredCharacters.empty())
|
||||
{
|
||||
for (auto& character : _registeredCharacters)
|
||||
|
||||
@@ -53,10 +53,14 @@ namespace Nuake
|
||||
mGBuffer->QueueResize(framebuffer.GetSize());
|
||||
GBufferPass(scene);
|
||||
|
||||
// SSAO
|
||||
const auto& sceneEnv = scene.GetEnvironment();
|
||||
sceneEnv->mSSAO->Resize(framebuffer.GetSize());
|
||||
sceneEnv->mSSAO->Draw(mGBuffer.get(), mProjection, mView);
|
||||
|
||||
mShadingBuffer->QueueResize(framebuffer.GetSize());
|
||||
ShadingPass(scene);
|
||||
|
||||
const auto& sceneEnv = scene.GetEnvironment();
|
||||
Ref<Texture> finalOutput = mShadingBuffer->GetTexture();
|
||||
if (scene.GetEnvironment()->BloomEnabled)
|
||||
{
|
||||
@@ -112,9 +116,7 @@ namespace Nuake
|
||||
|
||||
finalOutput = framebuffer.GetTexture();
|
||||
|
||||
// SSAO
|
||||
sceneEnv->mSSAO->Resize(framebuffer.GetSize());
|
||||
sceneEnv->mSSAO->Draw(mGBuffer.get(), mProjection, mView);
|
||||
|
||||
|
||||
// Copy final output to target framebuffer
|
||||
mToneMapBuffer->QueueResize(framebuffer.GetSize());
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Nuake {
|
||||
if (FileSystem::FileExists(path, false))
|
||||
{
|
||||
std::string prefabTextContent = FileSystem::ReadFile(path);
|
||||
newPrefab->Deserialize(prefabTextContent);
|
||||
newPrefab->Deserialize(json::parse(prefabTextContent));
|
||||
}
|
||||
|
||||
return newPrefab;
|
||||
|
||||
Reference in New Issue
Block a user