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 | |
10 | using namespace physx; |
11 | |
12 | namespace 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 | } |