Skip to content

Commit ebf5ccb

Browse files
committed
add new post about collision
1 parent 601b839 commit ebf5ccb

File tree

4 files changed

+107
-1
lines changed

4 files changed

+107
-1
lines changed

8.misc/blend_umg_ui_with_planar_reflection_in_material.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
UE4下实现UMG与PlanarReflection混合
1+
# UE4下实现UMG与PlanarReflection混合
22

33
![Sample](images/blend_umg_ui_with_planar_reflection_in_material.png)
44

8.misc/custom_collision_shape.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# UE4实现碰撞体的动态调整
2+
3+
## PrimitiveComponent的组成
4+
5+
UE4通过组合场景渲染代理(SceneProxy)和物理模拟实体(UBodySetup)完成PrimitiveComponent的创建。
6+
7+
![](images/primitive_component.png)
8+
9+
其中SceneProxy主要任务是告诉Renderer如何渲染当前PrimitiveComponent,
10+
BodySetup是Component实现物理模拟和碰撞检测的代理类,它以简化的几何体来表示实际模型的碰撞几何体(Box/Capsule/Convex)。
11+
12+
13+
因此为实现可动态改变的碰撞体,我们只要实现以下接口即可:
14+
15+
``` cpp
16+
//-------------- Collision Data Provider -------------------//
17+
virtual bool GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData) override;
18+
virtual bool ContainsPhysicsTriMeshData(bool InUseAllTriData) const override;
19+
virtual bool WantsNegXTriMesh() override;
20+
virtual void GetMeshId(FString& OutMeshId) override;
21+
//-------------- Collision Data Provider -------------------//
22+
```
23+
24+
## 通过PhysX Cook ConvexMesh完成BodySetup的创建
25+
26+
我们在Component完成注册的步骤上增加了程序化的碰撞体生成(见UpdateBodySetup方法):
27+
28+
``` cpp
29+
void UCircleTrack::OnRegister()
30+
{
31+
Super::OnRegister();
32+
UpdateBodySetup();
33+
}
34+
```
35+
36+
首先我们要创建新的BodySetup:
37+
38+
``` cpp
39+
UBodySetup* UCircleTrack::CreateBodySetup()
40+
{
41+
auto BodySetup = NewObject<UBodySetup>(this, NAME_None, (IsTemplate() ? RF_Public : RF_NoFlags));
42+
BodySetup->BodySetupGuid = FGuid::NewGuid();
43+
BodySetup->bGenerateMirroredCollision = false;
44+
BodySetup->bDoubleSidedGeometry = true;
45+
BodySetup->CollisionTraceFlag = bUseComplexAsSimple ? CTF_UseComplexAsSimple : CTF_UseDefault;
46+
return BodySetup;
47+
}
48+
```
49+
50+
然后程序通过计算生成新的凸包体(ConvexMesh, 由多个四面体组成):
51+
52+
``` cpp
53+
CollisionConvexElems.Reset();
54+
55+
...
56+
for (int32 i = 0; i < AngleSlice; i++)
57+
{
58+
FKConvexElem Elem;
59+
...
60+
Elem.VertexData.Add(...);
61+
Elem.ElemBox = FBox(Elem.VertexData);
62+
63+
CollisionConvexElems.Add(Elem);
64+
}
65+
```
66+
67+
最后调用PhysX Cook生成物理引擎使用的几何体:
68+
69+
``` cpp
70+
if (bUseAsyncCook)
71+
{
72+
AsyncBodySetupQueue.Add(CreateBodySetup());
73+
}
74+
else
75+
{
76+
AsyncBodySetupQueue.Empty();
77+
if (ArcBodySetup == nullptr)
78+
{
79+
ArcBodySetup = CreateBodySetup();
80+
}
81+
}
82+
UBodySetup* UseBodySetup = bUseAsyncCook ? AsyncBodySetupQueue.Last() : ArcBodySetup;
83+
UseBodySetup->AggGeom.ConvexElems = CollisionConvexElems;
84+
UseBodySetup->CollisionTraceFlag = bUseComplexAsSimple ? CTF_UseComplexAsSimple : CTF_UseDefault;
85+
/* 4.17 Support
86+
if (bUseAsyncCook)
87+
{
88+
UseBodySetup->CreatePhysicsMeshesAsync(FOnAsyncPhysicsCookFinished::CreateUObject(this, &UCircleTrack::FinishPhysicsAsyncCook, UseBodySetup));
89+
}
90+
else*/
91+
{
92+
// New GUID as collision has changed
93+
UseBodySetup->BodySetupGuid = FGuid::NewGuid();
94+
// Also we want cooked data for this
95+
UseBodySetup->bHasCookedCollisionData = true;
96+
UseBodySetup->InvalidatePhysicsData();
97+
UseBodySetup->CreatePhysicsMeshes(); // Cook Convex Mesh
98+
RecreatePhysicsState();
99+
}
100+
```
101+
102+
我们可以使用它来实现弧状的碰撞体,用于一些交互的响应,如下图:
103+
104+
![](images/custom_collision.png)
105+
106+
提供了如夹角、细分段数等参数调节。

8.misc/images/custom_collision.png

448 KB
Loading
6.93 KB
Loading

0 commit comments

Comments
 (0)