Chaos物理学习笔记一:Chaos物理碰撞体结构
对于一个StaticMesh来说,它的物理相关的数据都存在它的BodySetup的成员变量中。
对于每个StaticMesh来说,碰撞分为简单碰撞和复杂碰撞。
简单碰撞
简单碰撞相关的数据为UBodySetup的AggGeom成员变量
1 | class UBodySetup : public UBodySetupCore |
从上述代码不难看出简单碰撞类型有很多,包括:盒状、球状、胶囊体、凸包等。并且一个模型可以由多个简单碰撞体组成。
复杂碰撞
- 复杂碰撞的数据在UBodySetup里面为成员变量ChaosTriMeshes。在Cook的时候会序列化一份ChaosTriMeshes数据,然后运行时通过CreatePhysicsMeshes这个函数从序列化的数据中构建ChaosTriMeshes。
- 通常我们可以通过设置StaticMesh的Complex Collision Mesh来将别的模型设置为StaticMesh的用于复杂碰撞的模型(如果没有,则以LOD For Collision的LOD等级的原模型作为复杂碰撞的模型)
- 观察StaticMesh的代码:我们会发现ComplexCollisionMesh是一个只在编辑器下保存的数据。正如上文所说,复杂碰撞的数据会在Cook的时候被序列化下来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class UStaticMesh : public UStreamableRenderAsset, public IInterface_CollisionDataProvider, public IInterface_AssetUserData, public IInterface_AsyncCompilation
{
...
public:
UPROPERTY(Instanced)
TObjectPtr<class UObject> EditableMesh_DEPRECATED;
UPROPERTY(EditAnywhere, Category = Collision)
TObjectPtr<class UStaticMesh> ComplexCollisionMesh;
...
public:
ENGINE_API static void CheckLightMapUVs( UStaticMesh* InStaticMesh, TArray< FString >& InOutAssetsWithMissingUVSets, TArray< FString >& InOutAssetsWithBadUVSets, TArray< FString >& InOutAssetsWithValidUVSets, bool bInVerbose = true );
//~ Begin Interface_CollisionDataProvider Interface
ENGINE_API virtual bool GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData) override;
ENGINE_API virtual bool ContainsPhysicsTriMeshData(bool InUseAllTriData) const override;
ENGINE_API virtual bool PollAsyncPhysicsTriMeshData(bool InUseAllTriData) const override;
ENGINE_API virtual bool GetTriMeshSizeEstimates(struct FTriMeshCollisionDataEstimates& OutTriMeshEstimates, bool bInUseAllTriData) const override;
private:
bool GetPhysicsTriMeshDataCheckComplex(struct FTriMeshCollisionData* CollisionData, bool bInUseAllTriData, bool bInCheckComplexCollisionMesh);
bool ContainsPhysicsTriMeshDataCheckComplex(bool InUseAllTriData, bool bInCheckComplexCollisionMesh) const;
...
}
其中UBodySetup通过GetPhysicsTriMeshData
来获取生成复杂碰撞需要的数据也就是FTriMeshCollisionData* CollisionData
(通过这个数据我们也可以知道复杂碰撞准确的面数,当然这个数据仅限于编辑器下是准确的) - 另外,还有一个比较有意思的点,虚幻引擎无论是模型窗口还是关卡窗口,都有显示碰撞体的选项
但实际上会发现,如果设置了复杂碰撞(为了体现这一点,我还专门把模型的碰撞类型改为了 复杂碰撞用于简单),这两个窗口的显示是不一样的
那么到底哪个显示是正确的呢?答案是模型窗口下的显示是正确的。
原因是关卡窗口下的显示通过ShowFlag让StaticMesh的动态绘制路径中提供碰撞相关的数据可视化要用的MeshBatch,然而在这里StaticMesh只是提供了自身lod的渲染数据当作复杂碰撞的数据。
而在模型窗口下,”Complex Collision”按钮则比较正确的通过GetPhysicsTriMeshData
获取生成复杂碰撞需要的数据,然后再通过DrawLine画出复杂碰撞的线框。