2021SC@SDUSC
上篇我们进行flax Engine游戏引擎中物理引擎中physics(物理)内容的部分分析。讲述了光线和模拟物理系统中的一些函数定义和变量的源代码,本次我们紧接着上次的内容继续对flax Engine物理引擎中最关键的内容physics进行源代码的分析。
API_FUNCTION() static bool SphereCast(const Vector3& center, float radius, const Vector3& direction, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
此函数的功能是使用球体几何体对场景中的对象执行扫描测试。
参数为1:center 球体中心的位置 2:radius:球体半径 3:direction:投射球体的标准化方向 4:maxDistance:光线应检查碰撞的最大距离 5:layerMask:将命中触发器,否则将跳过它们 5:hitTriggers:如果球体命中匹配对象,则为True,否则为false。
API_FUNCTION() static bool SphereCastAll(const Vector3& center, float radius, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
此函数的功能是使用球体几何体对场景中的所有对象执行扫描测试。
与上述方法不同的是参数多了一个results:结果命中,仅当方法返回true时有效。
API_FUNCTION() static bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
此函数的功能是使用胶囊几何体对场景中的对象执行扫描测试。
相关参数:1:center:胶囊中心 2:radius:胶囊的半径 3:height:胶囊的高度,不包括顶部和底部球体 4:diection:投射胶囊的标准化方向 5:rotation:胶囊旋转 6:maxDIstance:光线应检查碰撞的最大距离 7:layerMask:如果设置为<c>true,将命中触发器,否则将跳过它们 8:返回值:如果胶囊命中匹配对象,则为True,否则为false。
API_FUNCTION() static bool CapsuleCastAll(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
此函数的功能是使用胶囊几何体对场景中的所有对象执行扫描测试。
与上述函数的区别是多一个参数:result 结果命中。仅当方法返回true时有效。
API_FUNCTION() static bool ConvexCast(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
此函数的功能是使用凸面网格对场景中的对象执行扫描测试。
相关参数:1:center :凸面网格中心 2:convexMesh :凸面网格的比例 3:scale:投影凸面网格的规格化方向 4:direction:投影凸面网格的规格化方向 5:rotation:凸面网格旋转 6:maxDistance:光线应检查碰撞的最大距离 7:hitTiggers: 如果设置为<c>true,将命中触发器,否则将跳过它们 8:返回值:如果凸面网格命中匹配对象,则为True,否则为false。
API_FUNCTION() static bool ConvexCastAll(const Vector3& center, const CollisionData* convexMesh, const Vector3& scale, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
此函数的功能是使用凸面网格对场景中的所有对象执行扫描测试。
于上述函数相比结果命中。仅当方法返回true时有效。
API_FUNCTION() static bool CheckBox(const Vector3& center, const Vector3& halfExtents, const Quaternion& rotation = Quaternion::Identity, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
此函数检查给定框是否与其他碰撞器重叠。
相关参数:1center:框的中心 2:halfExtents:框在每个方向上的一半大小 3:rotation框旋转 4:hitTriggers:如果设置为<c>true,将命中触发器,否则将跳过它们 5:返回值如果框与任何匹配对象重叠,则为True,否则为false。
API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
此函数是查找与给定球体接触或位于其内部的所有碰撞器。
相关参数:1:center:球体中心 2:radius:球体的半径 3:result:与给定球体重叠的结果碰撞器。仅当方法返回true时有效 4:hitTriggers:如果设置为<c>true,将命中触发器,否则将跳过它们。
.h文件中的public 公共函数:
1:启动函数,用来启动引擎的物理模拟
API_FUNCTION() static void Simulate(float dt);
在主机循环期间调用以启动物理模拟。之后使用CollectResults。
参数:三角洲时间。
.c文件中此函数的具体实现。
void Physics::Simulate(float dt)
{
ASSERT(IsInMainThread() && !_isDuringSimulation);
ASSERT(CPhysX);
const auto& settings = *PhysicsSettings::Get();
// Flush the old/new objects and the other requests before the simulation
FlushRequests();
// Clamp delta
dt = Math::Clamp(dt, 0.0f, settings.MaxDeltaTime);
// Prepare util objects
if (ScratchMemory == nullptr)
{
ScratchMemory = Allocator::Allocate(SCRATCH_BLOCK_SIZE, 16);
}
if (Stepper == nullptr)
{
Stepper = New<FixedStepper>();
}
if (settings.EnableSubstepping)
{
// Use substeps
Stepper->Setup(settings.SubstepDeltaTime, settings.MaxSubsteps);
}
else
{
// Use single step
Stepper->Setup(dt);
}
// Start simulation (may not be fired due to too small delta time)
_isDuringSimulation = true;
if (Stepper->advance(PhysicsScene, dt, ScratchMemory, SCRATCH_BLOCK_SIZE) == false)
return;
EventsCallback.Clear();
LastDeltaTime = dt;
// TODO: move this call after rendering done
Stepper->renderDone();
}
FlushRequests();在模拟之前刷新旧/新对象和其他请求
dt = Math::Clamp(dt, 0.0f, settings.MaxDeltaTime);抓紧
//准备util对象
if (ScratchMemory == nullptr)
{
ScratchMemory = Allocator::Allocate(SCRATCH_BLOCK_SIZE, 16);
}
if (Stepper == nullptr)
{
Stepper = New<FixedStepper>();
}
if (settings.EnableSubstepping)
{
// 使用子同步
Stepper->Setup(settings.SubstepDeltaTime, settings.MaxSubsteps);
}
else
{
//使用单步
Stepper->Setup(dt);
}启动模拟
if (Stepper->advance(PhysicsScene, dt, ScratchMemory, SCRATCH_BLOCK_SIZE) == false)
return;渲染完成后移动此调用
Stepper->renderDone();
2:公共函数:在主机循环期间调用,以收集物理模拟结果并将其应用于火灾碰撞事件。
API_FUNCTION() static void CollectResults();
在.c文件中的实现:
由于此函数的实现很长,我们在此仅仅对其重要的内容进行源代码的分析工作。
if (!_isDuringSimulation)
return;
ASSERT(IsInMainThread());
ASSERT(CPhysX && Stepper);
{
PROFILE_CPU_NAMED("Physics.Fetch");
// Gather results (with waiting for the end)
Stepper->wait(PhysicsScene);
}
首先:等待收集结果
if (WheelVehicles.HasItems()):如果有车
直接改变驾驶模式时自动换档
WheelVehiclesCache.Clear();
WheelVehiclesCache.EnsureCapacity(WheelVehicles.Count());
int32 wheelsCount = 0;
for (auto wheelVehicle : WheelVehicles)
{.........}更新批次查询缓存
if (wheelsCount > WheelQueryResults.Count())
{
if (WheelRaycastBatchQuery)
WheelRaycastBatchQuery->release();
WheelQueryResults.Resize(wheelsCount, false);
WheelHitResults.Resize(wheelsCount, false);
PxBatchQueryDesc desc(wheelsCount, 0, 0);
desc.queryMemory.userRaycastResultBuffer = WheelQueryResults.Get();
desc.queryMemory.userRaycastTouchBuffer = WheelHitResults.Get();
desc.queryMemory.raycastTouchBufferSize = wheelsCount;
desc.preFilterShader = WheelRaycastPreFilter;
WheelRaycastBatchQuery = PhysicsScene->createBatchQuery(desc);
}
3:公共函数:
检查物理模拟是否正在运行如果模拟处于活动状态,则为True,否则为false
API_PROPERTY() static bool IsDuringSimulation();
.c文件中的相关源代码的现实:
bool Physics::IsDuringSimulation()
{
return _isDuringSimulation;
}直接返回相关bool变量。