/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Code/EnginePlugins/JoltPlugin/Actors/Implementation/JoltDynamicActorComponent.cpp
487 строк
16 KB
C-Core
Water volume and VSE water shader (#1808)
04 фев 2026, 16:54
Не верифицирован
04 фев 2026, 16:54
5ad89f2
Код
Авторство
О чём код?
#include <JoltPlugin/JoltPluginPCH.h> #include <Core/Interfaces/PhysicsWorldModule.h> #include <Core/WorldSerializer/WorldReader.h> #include <Core/WorldSerializer/WorldWriter.h> #include <Foundation/Profiling/Profiling.h> #include <Jolt/Physics/Body/BodyCreationSettings.h> #include <Jolt/Physics/Collision/Shape/SphereShape.h> #include <Jolt/Physics/PhysicsSystem.h> #include <JoltPlugin/Actors/JoltDynamicActorComponent.h> #include <JoltPlugin/Resources/JoltMaterial.h> #include <JoltPlugin/Shapes/JoltShapeComponent.h> #include <JoltPlugin/System/JoltCollisionFiltering.h> #include <JoltPlugin/System/JoltCore.h> #include <JoltPlugin/System/JoltWorldModule.h> #include <JoltPlugin/Utilities/JoltConversionUtils.h> #include <Physics/Collision/Shape/OffsetCenterOfMassShape.h> ezJoltDynamicActorComponentManager::ezJoltDynamicActorComponentManager(ezWorld* pWorld) : ezComponentManager<ezJoltDynamicActorComponent, ezBlockStorageType::FreeList>(pWorld) { } ezJoltDynamicActorComponentManager::~ezJoltDynamicActorComponentManager() = default; void ezJoltDynamicActorComponentManager::UpdateDynamicActors() { EZ_PROFILE_SCOPE("UpdateDynamicActors"); ezJoltWorldModule* pModule = GetWorld()->GetOrCreateModule<ezJoltWorldModule>(); auto* pSystem = pModule->GetJoltSystem(); for (auto itActor : pModule->GetActiveActors()) { ezJoltDynamicActorComponent* pActor = itActor; JPH::BodyID bodyId(pActor->GetJoltBodyID()); JPH::BodyLockRead bodyLock(pSystem->GetBodyLockInterface(), bodyId); if (!bodyLock.Succeeded()) continue; const JPH::Body& body = bodyLock.GetBody(); if (!body.IsDynamic()) continue; ezSimdTransform trans = pActor->GetOwner()->GetGlobalTransformSimd(); trans.m_Position = ezJoltConversionUtils::ToSimdVec3(body.GetPosition()); trans.m_Rotation = ezJoltConversionUtils::ToSimdQuat(body.GetRotation()); pActor->GetOwner()->SetGlobalTransform(trans); } } void ezJoltDynamicActorComponentManager::UpdateKinematicActors(ezTime deltaTime) { EZ_PROFILE_SCOPE("UpdateKinematicActors"); ezJoltWorldModule* pModule = GetWorld()->GetOrCreateModule<ezJoltWorldModule>(); auto* pSystem = pModule->GetJoltSystem(); auto* pBodies = &pSystem->GetBodyInterface(); const float tDiff = deltaTime.AsFloatInSeconds(); for (auto pKinematicActorComponent : m_KinematicActorComponents) { JPH::BodyID bodyId(pKinematicActorComponent->m_uiJoltBodyID); if (bodyId.IsInvalid()) continue; ezGameObject* pObject = pKinematicActorComponent->GetOwner(); pObject->UpdateGlobalTransform(); const ezSimdVec4f pos = pObject->GetGlobalPositionSimd(); const ezSimdQuat rot = pObject->GetGlobalRotationSimd(); pBodies->MoveKinematic(bodyId, ezJoltConversionUtils::ToVec3(pos), ezJoltConversionUtils::ToQuat(rot).Normalized(), tDiff); } } ////////////////////////////////////////////////////////////////////////// // clang-format off EZ_BEGIN_COMPONENT_TYPE(ezJoltDynamicActorComponent, 8, ezComponentMode::Dynamic) { EZ_BEGIN_PROPERTIES { EZ_ACCESSOR_PROPERTY("Kinematic", GetKinematic, SetKinematic), EZ_MEMBER_PROPERTY("StartAsleep", m_bStartAsleep), EZ_MEMBER_PROPERTY("AllowSleeping", m_bAllowSleeping)->AddAttributes(new ezDefaultValueAttribute(true)), EZ_MEMBER_PROPERTY("WeightCategory", m_uiWeightCategory)->AddAttributes(new ezDynamicEnumAttribute("PhysicsWeightCategoryWithDensity")), EZ_ACCESSOR_PROPERTY("WeightScale", GetWeight_Scale, SetWeight_Scale)->AddAttributes(new ezDefaultValueAttribute(1.0f), new ezClampValueAttribute(0.1f, 10.0f)), EZ_ACCESSOR_PROPERTY("Mass", GetWeight_Mass, SetWeight_Mass)->AddAttributes(new ezSuffixAttribute(" kg"), new ezDefaultValueAttribute(10.0f), new ezClampValueAttribute(0.1f, 10000.0f)), EZ_ACCESSOR_PROPERTY("Density", GetWeight_Density, SetWeight_Density)->AddAttributes(new ezDefaultValueAttribute(100.0f), new ezSuffixAttribute(" kg/m^3")), EZ_ACCESSOR_PROPERTY("Surface", GetSurfaceFile, SetSurfaceFile)->AddAttributes(new ezAssetBrowserAttribute("CompatibleAsset_Surface", ezDependencyFlags::Package)), EZ_ACCESSOR_PROPERTY("GravityFactor", GetGravityFactor, SetGravityFactor)->AddAttributes(new ezDefaultValueAttribute(1.0f)), EZ_ACCESSOR_PROPERTY("BuoyancyFactor", GetBuoyancyFactor, SetBuoyancyFactor)->AddAttributes(new ezDefaultValueAttribute(1.1f), new ezClampValueAttribute(0.1f, 10.0f)), EZ_MEMBER_PROPERTY("LinearDamping", m_fLinearDamping)->AddAttributes(new ezDefaultValueAttribute(0.2f)), EZ_MEMBER_PROPERTY("AngularDamping", m_fAngularDamping)->AddAttributes(new ezDefaultValueAttribute(0.2f)), EZ_MEMBER_PROPERTY("ContinuousCollisionDetection", m_bCCD), EZ_BITFLAGS_MEMBER_PROPERTY("OnContact", ezOnJoltContact, m_OnContact), EZ_ACCESSOR_PROPERTY("CustomCenterOfMass", GetUseCustomCoM, SetUseCustomCoM), EZ_MEMBER_PROPERTY("CenterOfMass", m_vCenterOfMass), } EZ_END_PROPERTIES; EZ_BEGIN_MESSAGEHANDLERS { EZ_MESSAGE_HANDLER(ezMsgPhysicsAddImpulse, AddLinearImpulseAtPos), } EZ_END_MESSAGEHANDLERS; EZ_BEGIN_FUNCTIONS { EZ_SCRIPT_FUNCTION_PROPERTY(AddLinearImpulse, In, "vImpulse", In, "uiImpulseType")->AddAttributes(new ezFunctionArgumentAttributes(1, new ezDefaultValueAttribute(0))), EZ_SCRIPT_FUNCTION_PROPERTY(AddAngularImpulse, In, "vImpulse", In, "uiImpulseType")->AddAttributes(new ezFunctionArgumentAttributes(1, new ezDefaultValueAttribute(0))), EZ_SCRIPT_FUNCTION_PROPERTY(AddOrUpdateForce, In, "uiForceID", In, "duration", In, "vForce"), EZ_SCRIPT_FUNCTION_PROPERTY(ClearForce, In, "uiForceID"), } EZ_END_FUNCTIONS; EZ_BEGIN_ATTRIBUTES { new ezTransformManipulatorAttribute("CenterOfMass") } EZ_END_ATTRIBUTES; } EZ_END_COMPONENT_TYPE // clang-format on ezJoltDynamicActorComponent::ezJoltDynamicActorComponent() { m_uiJoltBodyID = JPH::BodyID::cInvalidBodyID; } ezJoltDynamicActorComponent::~ezJoltDynamicActorComponent() = default; void ezJoltDynamicActorComponent::SerializeComponent(ezWorldWriter& inout_stream) const { SUPER::SerializeComponent(inout_stream); auto& s = inout_stream.GetStream(); s << m_bKinematic; s << m_bCCD; s << m_fLinearDamping; s << m_fAngularDamping; s << m_fGravityFactor; s << m_hSurface; s << m_OnContact; s << GetUseCustomCoM(); s << m_vCenterOfMass; s << m_bStartAsleep; s << m_bAllowSleeping; s << m_uiWeightCategory; s << (float)m_fWeightScale; s << (float)m_fWeightMass; s << (float)m_fWeightDensity; s << (float)m_fBuoyancyFactor; } void ezJoltDynamicActorComponent::DeserializeComponent(ezWorldReader& inout_stream) { SUPER::DeserializeComponent(inout_stream); const ezUInt32 uiVersion = inout_stream.GetComponentTypeVersion(GetStaticRTTI()); EZ_ASSERT_DEBUG(uiVersion >= 7, "Outdated version, please re-transform asset."); if (uiVersion < 7) return; auto& s = inout_stream.GetStream(); s >> m_bKinematic; s >> m_bCCD; s >> m_fLinearDamping; s >> m_fAngularDamping; s >> m_fGravityFactor; s >> m_hSurface; s >> m_OnContact; { bool com; s >> com; SetUseCustomCoM(com); s >> m_vCenterOfMass; } s >> m_bStartAsleep; s >> m_bAllowSleeping; { float f; s >> m_uiWeightCategory; s >> f; m_fWeightScale = f; s >> f; m_fWeightMass = f; s >> f; m_fWeightDensity = f; } if (uiVersion >= 8) { float f; s >> f; m_fBuoyancyFactor = f; } } void ezJoltDynamicActorComponent::SetKinematic(bool b) { if (m_bKinematic == b) return; m_bKinematic = b; JPH::BodyID bodyId(m_uiJoltBodyID); if (m_bKinematic && !bodyId.IsInvalid()) { // do not insert this, until we actually have an actor pointer GetWorld()->GetOrCreateComponentManager<ezJoltDynamicActorComponentManager>()->m_KinematicActorComponents.PushBack(this); } else { GetWorld()->GetOrCreateComponentManager<ezJoltDynamicActorComponentManager>()->m_KinematicActorComponents.RemoveAndSwap(this); } if (bodyId.IsInvalid()) return; ezJoltWorldModule* pModule = GetWorld()->GetOrCreateModule<ezJoltWorldModule>(); auto* pSystem = pModule->GetJoltSystem(); { JPH::BodyLockWrite bodyLock(pSystem->GetBodyLockInterface(), bodyId); if (bodyLock.Succeeded()) { JPH::Body& body = bodyLock.GetBody(); body.SetMotionType(m_bKinematic ? JPH::EMotionType::Kinematic : JPH::EMotionType::Dynamic); } } if (!m_bKinematic && pSystem->GetBodyInterface().IsAdded(bodyId)) { pSystem->GetBodyInterface().ActivateBody(bodyId); } } void ezJoltDynamicActorComponent::SetGravityFactor(float fFactor) { if (m_fGravityFactor == fFactor) return; m_fGravityFactor = fFactor; JPH::BodyID bodyId(m_uiJoltBodyID); if (bodyId.IsInvalid()) return; auto* pSystem = GetWorld()->GetOrCreateModule<ezJoltWorldModule>()->GetJoltSystem(); JPH::BodyLockWrite bodyLock(pSystem->GetBodyLockInterface(), bodyId); if (bodyLock.Succeeded()) { bodyLock.GetBody().GetMotionProperties()->SetGravityFactor(m_fGravityFactor); if (pSystem->GetBodyInterfaceNoLock().IsAdded(bodyId)) { pSystem->GetBodyInterfaceNoLock().ActivateBody(bodyId); } } } void ezJoltDynamicActorComponent::OnSimulationStarted() { SUPER::OnSimulationStarted(); ezJoltWorldModule* pModule = GetWorld()->GetOrCreateModule<ezJoltWorldModule>(); const ezSimdTransform trans = GetOwner()->GetGlobalTransformSimd(); auto* pSystem = pModule->GetJoltSystem(); auto* pBodies = &pSystem->GetBodyInterface(); auto* pMaterial = GetJoltMaterial(); JPH::BodyCreationSettings bodyCfg; if (CreateShape(&bodyCfg, m_fWeightDensity, pMaterial).Failed()) { ezLog::Error("Jolt dynamic actor component '{}' has no valid shape.", GetOwner()->GetName()); return; } if (pMaterial == nullptr) pMaterial = ezJoltCore::GetDefaultMaterial(); ezJoltUserData* pUserData = nullptr; m_uiUserDataIndex = pModule->AllocateUserData(pUserData); pUserData->Init(this, m_OnContact); const float fInitialMass = ezJoltCore::GetWeightCategoryConfig().GetMassForWeightCategory(m_uiWeightCategory, 10.0f, m_fWeightMass, m_fWeightScale); bodyCfg.mPosition = ezJoltConversionUtils::ToVec3(trans.m_Position); bodyCfg.mRotation = ezJoltConversionUtils::ToQuat(trans.m_Rotation).Normalized(); bodyCfg.mMotionType = m_bKinematic ? JPH::EMotionType::Kinematic : JPH::EMotionType::Dynamic; bodyCfg.mObjectLayer = ezJoltCollisionFiltering::ConstructObjectLayer(m_uiCollisionLayer, ezJoltBroadphaseLayer::Dynamic); bodyCfg.mMotionQuality = m_bCCD ? JPH::EMotionQuality::LinearCast : JPH::EMotionQuality::Discrete; bodyCfg.mAllowSleeping = m_bAllowSleeping; bodyCfg.mLinearDamping = m_fLinearDamping; bodyCfg.mAngularDamping = m_fAngularDamping; bodyCfg.mMassPropertiesOverride.mMass = fInitialMass; bodyCfg.mOverrideMassProperties = fInitialMass > 0.0f ? JPH::EOverrideMassProperties::CalculateInertia : JPH::EOverrideMassProperties::CalculateMassAndInertia; bodyCfg.mGravityFactor = m_fGravityFactor; bodyCfg.mRestitution = pMaterial->m_fRestitution; bodyCfg.mFriction = pMaterial->m_fFriction; bodyCfg.mCollisionGroup.SetGroupID(m_uiObjectFilterID); bodyCfg.mCollisionGroup.SetGroupFilter(pModule->GetGroupFilter()); bodyCfg.mUserData = reinterpret_cast<ezUInt64>(pUserData); if (GetUseCustomCoM()) { const ezVec3 vGlobalScale = GetOwner()->GetGlobalScaling(); const float scale = ezMath::Min(vGlobalScale.x, vGlobalScale.y, vGlobalScale.z); auto vLocalCenterOfMass = ezSimdVec4f(scale * m_vCenterOfMass.x, scale * m_vCenterOfMass.y, scale * m_vCenterOfMass.z); auto vPrevCoM = ezJoltConversionUtils::ToSimdVec3(bodyCfg.GetShape()->GetCenterOfMass()); auto vComShift = vLocalCenterOfMass - vPrevCoM; JPH::OffsetCenterOfMassShapeSettings com; com.mOffset = ezJoltConversionUtils::ToVec3(vComShift); com.mInnerShapePtr = bodyCfg.GetShape(); bodyCfg.SetShape(com.Create().Get()); } JPH::Body* pBody = pBodies->CreateBody(bodyCfg); EZ_ASSERT_DEV(pBody != nullptr, "Jolt body creation failed. You need to increase the maximum number of bodies."); m_uiJoltBodyID = pBody->GetID().GetIndexAndSequenceNumber(); pModule->QueueBodyToAdd(pBody, !m_bStartAsleep); if (m_bKinematic) { GetWorld()->GetOrCreateComponentManager<ezJoltDynamicActorComponentManager>()->m_KinematicActorComponents.PushBack(this); } } void ezJoltDynamicActorComponent::OnDeactivated() { if (m_bKinematic) { GetWorld()->GetOrCreateComponentManager<ezJoltDynamicActorComponentManager>()->m_KinematicActorComponents.RemoveAndSwap(this); } auto allConstraints = m_Constraints; m_Constraints.Clear(); m_Constraints.Compact(); ezJoltMsgDisconnectConstraints msg; msg.m_pActor = this; msg.m_uiJoltBodyID = GetJoltBodyID(); ezWorld* pWorld = GetWorld(); for (ezComponentHandle hConstraint : allConstraints) { pWorld->SendMessage(hConstraint, msg); } SUPER::OnDeactivated(); } void ezJoltDynamicActorComponent::AddLinearImpulse(const ezVec3& vImpulse, ezUInt8 uiImpulseType) { if (m_bKinematic || m_uiJoltBodyID == ezInvalidIndex) return; const float fImpulse = ezJoltCore::GetImpulseTypeConfig().GetImpulseForWeight(uiImpulseType, m_uiWeightCategory); GetWorld()->GetModule<ezJoltWorldModule>()->AddImpulse(m_uiJoltBodyID, vImpulse * fImpulse); } void ezJoltDynamicActorComponent::AddAngularImpulse(const ezVec3& vImpulse, ezUInt8 uiImpulseType) { if (m_bKinematic || m_uiJoltBodyID == ezInvalidIndex) return; const float fImpulse = ezJoltCore::GetImpulseTypeConfig().GetImpulseForWeight(uiImpulseType, m_uiWeightCategory); GetWorld()->GetModule<ezJoltWorldModule>()->AddTorque(m_uiJoltBodyID, vImpulse * fImpulse); } void ezJoltDynamicActorComponent::AddConstraint(ezComponentHandle hComponent) { m_Constraints.PushBack(hComponent); } void ezJoltDynamicActorComponent::RemoveConstraint(ezComponentHandle hComponent) { m_Constraints.RemoveAndSwap(hComponent); } void ezJoltDynamicActorComponent::AddLinearImpulseAtPos(ezMsgPhysicsAddImpulse& ref_msg) { if (m_bKinematic || m_uiJoltBodyID == ezInvalidIndex) return; const float fImpulse = ezJoltCore::GetImpulseTypeConfig().GetImpulseForWeight(ref_msg.m_uiImpulseType, m_uiWeightCategory); GetWorld()->GetModule<ezJoltWorldModule>()->AddImpulse(m_uiJoltBodyID, ref_msg.m_vImpulse * fImpulse, ref_msg.m_vGlobalPosition); } float ezJoltDynamicActorComponent::GetMass() const { if (m_bKinematic || m_uiJoltBodyID == ezInvalidIndex) return 0.0f; auto& bodyLockInterface = GetWorld()->GetModule<ezJoltWorldModule>()->GetJoltSystem()->GetBodyLockInterface(); JPH::BodyLockRead bodyLock(bodyLockInterface, JPH::BodyID(m_uiJoltBodyID)); const float fInverseMass = bodyLock.GetBody().GetMotionProperties()->GetInverseMass(); return fInverseMass > 0.0f ? 1.0f / fInverseMass : 0.0f; } ezUInt32 ezJoltDynamicActorComponent::AddOrUpdateForce(ezUInt32 uiForceID, ezTime duration, const ezVec3& vForce) { if (m_uiJoltBodyID == ezInvalidIndex) return 0; ezJoltWorldModule* pModule = GetWorld()->GetModule<ezJoltWorldModule>(); ezJoltForceId forceID(uiForceID); return pModule->AddOrUpdateForce(forceID, m_uiJoltBodyID, duration, vForce).m_Data; } void ezJoltDynamicActorComponent::ClearForce(ezUInt32 uiForceID) { ezJoltWorldModule* pModule = GetWorld()->GetModule<ezJoltWorldModule>(); ezJoltForceId forceID(uiForceID); pModule->ClearForce(forceID); } const ezJoltMaterial* ezJoltDynamicActorComponent::GetJoltMaterial() const { if (m_hSurface.IsValid()) { ezResourceLock<ezSurfaceResource> pSurface(m_hSurface, ezResourceAcquireMode::BlockTillLoaded); if (pSurface->m_pPhysicsMaterialJolt != nullptr) { return static_cast<ezJoltMaterial*>(pSurface->m_pPhysicsMaterialJolt); } } return nullptr; } void ezJoltDynamicActorComponent::SetSurfaceFile(ezStringView sFile) { if (!sFile.IsEmpty()) { m_hSurface = ezResourceManager::LoadResource<ezSurfaceResource>(sFile); } else { m_hSurface = {}; } if (m_hSurface.IsValid()) ezResourceManager::PreloadResource(m_hSurface); } ezStringView ezJoltDynamicActorComponent::GetSurfaceFile() const { if (!m_hSurface.IsValid()) return ""; return m_hSurface.GetResourceID(); } EZ_STATICLINK_FILE(JoltPlugin, JoltPlugin_Actors_Implementation_JoltDynamicActorComponent);