1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "BsFPhysXCollider.h"
4#include "BsPhysX.h"
5#include "BsPhysXRigidbody.h"
6#include "BsPhysXMaterial.h"
7#include "PxScene.h"
8#include "PxShape.h"
9
10using namespace physx;
11
12namespace bs
13{
14 FPhysXCollider::FPhysXCollider(PxScene* scene, PxShape* shape)
15 :mScene(scene), mShape(shape)
16 {
17 mStaticBody = gPhysX().getPhysX()->createRigidStatic(PxTransform(PxIdentity));
18 mStaticBody->attachShape(*mShape);
19
20 mScene->addActor(*mStaticBody);
21
22 updateFilter();
23 }
24
25 FPhysXCollider::~FPhysXCollider()
26 {
27 if (mStaticBody != nullptr)
28 mStaticBody->release();
29
30 mShape->userData = nullptr;
31 mShape->release();
32 }
33
34 void FPhysXCollider::_setShape(PxShape* shape)
35 {
36 if (mShape != nullptr)
37 {
38 shape->setLocalPose(mShape->getLocalPose());
39 shape->setFlags(mShape->getFlags());
40 shape->setContactOffset(mShape->getContactOffset());
41 shape->setRestOffset(mShape->getRestOffset());
42
43 UINT32 numMaterials = mShape->getNbMaterials();
44 UINT32 bufferSize = sizeof(PxMaterial*) * numMaterials;
45 PxMaterial** materials = (PxMaterial**)bs_stack_alloc(bufferSize);
46
47 mShape->getMaterials(materials, bufferSize);
48 shape->setMaterials(materials, numMaterials);
49 shape->userData = mShape->userData;
50
51 bs_stack_free(materials);
52
53 PxActor* actor = mShape->getActor();
54 if (actor != nullptr)
55 {
56 PxRigidActor* rigidActor = actor->is<PxRigidActor>();
57 if (rigidActor != nullptr)
58 {
59 rigidActor->detachShape(*mShape);
60 rigidActor->attachShape(*shape);
61 }
62 }
63 }
64
65 mShape = shape;
66
67 updateFilter();
68 }
69
70 Vector3 FPhysXCollider::getPosition() const
71 {
72 return fromPxVector(mShape->getLocalPose().p);
73 }
74
75 Quaternion FPhysXCollider::getRotation() const
76 {
77 return fromPxQuaternion(mShape->getLocalPose().q);
78 }
79
80 void FPhysXCollider::setTransform(const Vector3& pos, const Quaternion& rotation)
81 {
82 mShape->setLocalPose(toPxTransform(pos, rotation));
83 }
84
85 void FPhysXCollider::setIsTrigger(bool value)
86 {
87 if(value)
88 {
89 mShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
90 mShape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
91
92 mIsTrigger = true;
93 }
94 else
95 {
96 mShape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, false);
97 mShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
98
99 mIsTrigger = false;
100 }
101 }
102
103 bool FPhysXCollider::getIsTrigger() const
104 {
105 return (UINT32)(mShape->getFlags() & PxShapeFlag::eTRIGGER_SHAPE) != 0;
106 }
107
108 void FPhysXCollider::setIsStatic(bool value)
109 {
110 if (mIsStatic == value)
111 return;
112
113 if (mStaticBody != nullptr)
114 {
115 mStaticBody->detachShape(*mShape);
116
117 mStaticBody->release();
118 mStaticBody = nullptr;
119 }
120
121 mIsStatic = value;
122
123 if (mIsStatic)
124 {
125 mStaticBody = gPhysX().getPhysX()->createRigidStatic(PxTransform(PxIdentity));
126 mStaticBody->attachShape(*mShape);
127
128 mScene->addActor(*mStaticBody);
129 }
130 }
131
132 bool FPhysXCollider::getIsStatic() const
133 {
134 return mIsStatic;
135 }
136
137 void FPhysXCollider::setContactOffset(float value)
138 {
139 mShape->setContactOffset(value);
140 }
141
142 float FPhysXCollider::getContactOffset() const
143 {
144 return mShape->getContactOffset();
145 }
146
147 void FPhysXCollider::setRestOffset(float value)
148 {
149 mShape->setRestOffset(value);
150 }
151
152 float FPhysXCollider::getRestOffset() const
153 {
154 return mShape->getRestOffset();
155 }
156
157 void FPhysXCollider::setMaterial(const HPhysicsMaterial& material)
158 {
159 FCollider::setMaterial(material);
160
161 PhysXMaterial* physXmaterial = nullptr;
162 if(material.isLoaded())
163 physXmaterial = static_cast<PhysXMaterial*>(material.get());
164
165 PxMaterial* materials[1];
166 if (physXmaterial != nullptr)
167 materials[0] = physXmaterial->_getInternal();
168 else
169 materials[0] = gPhysX().getDefaultMaterial();
170
171 mShape->setMaterials(materials, sizeof(materials) / sizeof(materials[0]));
172 }
173
174 UINT64 FPhysXCollider::getLayer() const
175 {
176 return mLayer;
177 }
178
179 void FPhysXCollider::setLayer(UINT64 layer)
180 {
181 mLayer = layer;
182 updateFilter();
183 }
184
185 CollisionReportMode FPhysXCollider::getCollisionReportMode() const
186 {
187 return mCollisionReportMode;
188 }
189
190 void FPhysXCollider::setCollisionReportMode(CollisionReportMode mode)
191 {
192 mCollisionReportMode = mode;
193 updateFilter();
194 }
195
196 void FPhysXCollider::_setCCD(bool enabled)
197 {
198 mCCD = enabled;
199 updateFilter();
200 }
201
202 void FPhysXCollider::updateFilter()
203 {
204 PxFilterData data;
205 memcpy(&data.word0, &mLayer, sizeof(mLayer));
206
207 PhysXObjectFilterFlags flags;
208
209 switch(mCollisionReportMode)
210 {
211 case CollisionReportMode::None:
212 flags |= PhysXObjectFilterFlag::NoReport;
213 break;
214 case CollisionReportMode::Report:
215 flags |= PhysXObjectFilterFlag::ReportBasic;
216 break;
217 case CollisionReportMode::ReportPersistent:
218 flags |= PhysXObjectFilterFlag::ReportAll;
219 break;
220 }
221
222 if (mCCD)
223 flags |= PhysXObjectFilterFlag::CCD;
224
225 data.word2 = flags;
226
227 mShape->setSimulationFilterData(data);
228 mShape->setQueryFilterData(data);
229 }
230}