Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qphysxactorbody.cpp
Go to the documentation of this file.
1
// Copyright (C) 2023 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#
include
"qphysxactorbody_p.h"
6
7
#
include
"PxMaterial.h"
8
#
include
"PxPhysics.h"
9
#
include
"PxRigidDynamic.h"
10
#
include
"PxRigidActor.h"
11
#
include
"PxScene.h"
12
13
#
include
"physxnode/qphysxworld_p.h"
14
#
include
"qabstractphysicsbody_p.h"
15
#
include
"qheightfieldshape_p.h"
16
#
include
"qphysicsutils_p.h"
17
#
include
"qplaneshape_p.h"
18
#
include
"qstaticphysxobjects_p.h"
19
20
#
include
<
QtGui
/
qquaternion
.
h
>
21
22
#
define
PHYSX_RELEASE
(
x
)
23
if
(
x
!=
nullptr
)
{
24
x
->
release
(
)
;
25
x
=
nullptr
;
26
}
27
28
QT_BEGIN_NAMESPACE
29
30
static
physx
::
PxTransform
getPhysXLocalTransform
(
const
QQuick3DNode *node)
31
{
32
// Modify transforms to make the PhysX shapes match the QtQuick3D conventions
33
if
(qobject_cast<
const
QPlaneShape *>(node) !=
nullptr
) {
34
// Rotate the plane to make it match the built-in rectangle
35
const
QQuaternion rotation = QPhysicsUtils::kMinus90YawRotation * node->rotation();
36
return
physx::PxTransform(QPhysicsUtils::toPhysXType(node->position()),
37
QPhysicsUtils::toPhysXType(rotation));
38
}
else
if
(
auto
*hf = qobject_cast<
const
QHeightFieldShape *>(node)) {
39
// Shift the height field so it's centered at the origin
40
return
physx::PxTransform(QPhysicsUtils::toPhysXType(node->position() + hf->hfOffset()),
41
QPhysicsUtils::toPhysXType(node->rotation()));
42
}
43
44
const
QQuaternion &rotation = node->rotation();
45
const
QVector3D
&localPosition = node->position();
46
const
QVector3D
&scale = node->sceneScale();
47
return
physx::PxTransform(QPhysicsUtils::toPhysXType(localPosition * scale),
48
QPhysicsUtils::toPhysXType(rotation));
49
}
50
51
QPhysXActorBody
::QPhysXActorBody(QAbstractPhysicsNode *frontEnd) :
QAbstractPhysXNode
(frontEnd) { }
52
53
void
QPhysXActorBody
::
cleanup
(
QPhysXWorld
*physX)
54
{
55
if
(
actor
) {
56
physX
->
scene
->removeActor(*
actor
);
57
PHYSX_RELEASE
(
actor
);
58
}
59
QAbstractPhysXNode
::
cleanup
(physX);
60
}
61
62
void
QPhysXActorBody
::
init
(QPhysicsWorld *
/*world*/
,
QPhysXWorld
*physX)
63
{
64
Q_ASSERT(!
actor
);
65
66
updateMaterial
();
67
createActor
(
physX
)
;
68
69
actor
->userData =
reinterpret_cast
<
void
*>(frontendNode);
70
physX
->
scene
->addActor(*
actor
);
71
setShapesDirty
(
true
);
72
}
73
74
void
QPhysXActorBody
::
sync
(
float
/*deltaTime*/
,
75
QHash<QQuick3DNode *, QMatrix4x4> &
/*transformCache*/
)
76
{
77
// The physicsMaterial property, and the properties of the material itself, can change while
78
// the simulation is running. Materials are shared between all nodes that need the same
79
// properties, so rather than modifying the material in place, the node is moved to the
80
// material with the new properties, and its shapes are pointed at it.
81
if
(updateMaterial() && material) {
82
for
(
auto
*shape : std::as_const(shapes))
83
shape->setMaterials(&material, 1);
84
}
85
}
86
87
void
QPhysXActorBody
::
markDirtyShapes
()
88
{
89
if
(!frontendNode || !actor)
90
return
;
91
92
// Go through the shapes and look for a change in pose (rotation, position)
93
// TODO: it is likely cheaper to connect a signal for changes on the position and rotation
94
// property and mark the node dirty then.
95
if
(!
shapesDirty
()) {
96
const
auto
&collisionShapes = frontendNode->getCollisionShapesList();
97
const
auto
&physXShapes = shapes;
98
99
const
int
len = collisionShapes.size();
100
if
(physXShapes.size() != len) {
101
// This should not really happen but check it anyway
102
setShapesDirty
(
true
);
103
}
else
{
104
for
(
int
i = 0; i < len; i++) {
105
auto
poseNew = getPhysXLocalTransform(collisionShapes[i]);
106
auto
poseOld = physXShapes[i]->getLocalPose();
107
108
if
(!QPhysicsUtils::fuzzyEquals(poseNew, poseOld)) {
109
setShapesDirty
(
true
);
110
break
;
111
}
112
}
113
}
114
}
115
}
116
117
void
QPhysXActorBody
::
rebuildDirtyShapes
(QPhysicsWorld *
/*world*/
,
QPhysXWorld
*physX)
118
{
119
if
(!
shapesDirty
())
120
return
;
121
buildShapes
(
physX
)
;
122
setShapesDirty
(
false
);
123
}
124
125
void
QPhysXActorBody
::
detachFrontend
()
126
{
127
if
(
actor
)
128
actor
->userData =
nullptr
;
129
QAbstractPhysXNode
::
detachFrontend
();
130
}
131
132
void
QPhysXActorBody
::
createActor
(
QPhysXWorld
*
/*physX*/
)
133
{
134
auto
&s_physx =
StaticPhysXObjects
::
getReference
(
)
;
135
physx
::
PxTransform
trf = QPhysicsUtils::toPhysXTransform(frontendNode->scenePosition(),
136
frontendNode->sceneRotation());
137
if
(!trf.isSane()) {
138
qWarning() <<
"PhysicsNode: position/rotation is not finite, using identity instead."
;
139
trf = physx::PxTransform(physx::PxIdentity);
140
}
141
auto
*dynamicActor = s_physx
.
physics
->createRigidDynamic(trf);
142
143
// A trigger has to be a dynamic actor, since PhysX only reports a trigger
144
// pair when one of the two is, but it is not simulated and nothing reads
145
// the velocity gravity would give it. Without gravity it stays where it is
146
// put and can fall asleep, which is what stops its pairs being tested:
147
// PhysX skips a trigger pair's overlap test only when both of its actors
148
// are asleep (see Sc::TriggerInteraction).
149
if
(
useTriggerFlag
())
150
dynamicActor->setActorFlag(physx::PxActorFlag::eDISABLE_GRAVITY,
true
);
151
152
actor
= dynamicActor;
153
}
154
155
bool
QPhysXActorBody
::
debugGeometryCapability
()
156
{
157
return
true
;
158
}
159
160
physx
::
PxTransform
QPhysXActorBody
::
getGlobalPose
()
161
{
162
return
actor
->getGlobalPose();
163
}
164
165
void
QPhysXActorBody
::
buildShapes
(
QPhysXWorld
*
/*physX*/
)
166
{
167
auto
body =
actor
;
168
for
(
auto
*shape : std::as_const(shapes)) {
169
body->detachShape(*shape);
170
PHYSX_RELEASE
(shape);
171
}
172
173
// TODO: Only remove changed shapes?
174
shapes.clear();
175
176
for
(
const
auto
&collisionShape : frontendNode->getCollisionShapesList()) {
177
auto
*geom = collisionShape->getPhysXGeometry();
178
if
(!geom || !material)
179
continue
;
180
181
auto
&s_physx = StaticPhysXObjects::getReference();
182
// The shape is created exclusive to this actor: a shape that may be shared between
183
// actors cannot be modified once it is attached to one, and these shapes are modified
184
// while attached, for instance when their filter data changes.
185
auto
physXShape = s_physx.physics->createShape(*geom, *material,
true
);
186
if
(!physXShape) {
187
qWarning() <<
"QtQuick3DPhysics: could not create shape, invalid geometry."
;
188
continue
;
189
}
190
191
// Ties the PxShape back to the collision shape it was built for: a
192
// trigger pair is matched by those, which survive a rebuild replacing
193
// every PxShape of a node.
194
physXShape->userData =
reinterpret_cast
<
void
*>(collisionShape);
195
196
if
(useTriggerFlag()) {
197
physXShape->setFlag(physx::PxShapeFlag::eSCENE_QUERY_SHAPE,
false
);
198
physXShape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,
false
);
199
physXShape->setFlag(physx::PxShapeFlag::eTRIGGER_SHAPE,
true
);
200
}
201
202
{
// Setup filtering
203
physx::PxFilterData filterData;
204
filterData.word0 = frontendNode->filterGroup();
205
filterData.word1 = frontendNode->filterIgnoreGroups();
206
physXShape->setSimulationFilterData(filterData);
207
}
208
209
physx::PxTransform localPose = getPhysXLocalTransform(collisionShape);
210
if
(!localPose.isSane()) {
211
qWarning() <<
"QtQuick3DPhysics: collision shape position/rotation is not finite, "
212
"using identity local pose instead."
;
213
localPose = physx::PxTransform(physx::PxIdentity);
214
}
215
physXShape->setLocalPose(localPose);
216
217
// A shape PhysX will not take is not kept: left in 'shapes' it would make
218
// markDirtyShapes() find the body's shapes to be in order, so nothing would
219
// ever rebuild them, and the next rebuild would detach a shape that had never
220
// been attached.
221
if
(!body->attachShape(*physXShape)) {
222
qWarning() <<
"QtQuick3DPhysics: could not attach collision shape to body, it will "
223
"not take part in the simulation."
;
224
PHYSX_RELEASE
(physXShape);
225
continue
;
226
}
227
228
shapes.push_back(physXShape);
229
}
230
231
// Filters are always clean after building shapes
232
setFiltersDirty
(
false
);
233
}
234
235
void
QPhysXActorBody
::
updateFilters
()
236
{
237
if
(!
filtersDirty
())
238
return
;
239
240
// Go through all shapes and set the filter group and mask.
241
// TODO: What about shared shapes on several actors?
242
for
(
auto
&physXShape : shapes) {
243
physx::PxFilterData filterData;
244
filterData.word0 = frontendNode->filterGroup();
245
filterData.word1 = frontendNode->filterIgnoreGroups();
246
physXShape->setSimulationFilterData(filterData);
247
}
248
249
setFiltersDirty
(
false
);
250
}
251
252
QT_END_NAMESPACE
QAbstractPhysXNode
Definition
qabstractphysxnode_p.h:58
QAbstractPhysXNode::filtersDirty
bool filtersDirty() const
Definition
qabstractphysxnode.cpp:156
QAbstractPhysXNode::cleanup
virtual void cleanup(QPhysXWorld *)
Definition
qabstractphysxnode.cpp:118
QAbstractPhysXNode::shapesDirty
bool shapesDirty() const
Definition
qabstractphysxnode.cpp:146
QAbstractPhysXNode::setShapesDirty
void setShapesDirty(bool dirty)
Definition
qabstractphysxnode.cpp:151
QAbstractPhysXNode::updateMaterial
bool updateMaterial()
Definition
qabstractphysxnode.cpp:66
QAbstractPhysXNode::setFiltersDirty
void setFiltersDirty(bool dirty)
Definition
qabstractphysxnode.cpp:161
QAbstractPhysXNode::detachFrontend
virtual void detachFrontend()
Definition
qabstractphysxnode.cpp:167
QAbstractPhysXNode::useTriggerFlag
virtual bool useTriggerFlag()
Definition
qabstractphysxnode.cpp:136
QPhysXActorBody
Definition
qphysxactorbody_p.h:29
QPhysXActorBody::markDirtyShapes
void markDirtyShapes() override
Definition
qphysxactorbody.cpp:87
QPhysXActorBody::buildShapes
void buildShapes(QPhysXWorld *physX)
Definition
qphysxactorbody.cpp:165
QPhysXActorBody::rebuildDirtyShapes
void rebuildDirtyShapes(QPhysicsWorld *world, QPhysXWorld *physX) override
Definition
qphysxactorbody.cpp:117
QPhysXActorBody::init
void init(QPhysicsWorld *world, QPhysXWorld *physX) override
Definition
qphysxactorbody.cpp:62
QPhysXActorBody::detachFrontend
void detachFrontend() override
Definition
qphysxactorbody.cpp:125
QPhysXActorBody::debugGeometryCapability
bool debugGeometryCapability() override
Definition
qphysxactorbody.cpp:155
QPhysXActorBody::cleanup
void cleanup(QPhysXWorld *physX) override
Definition
qphysxactorbody.cpp:53
QPhysXActorBody::actor
physx::PxRigidActor * actor
Definition
qphysxactorbody_p.h:46
QPhysXActorBody::createActor
virtual void createActor(QPhysXWorld *physX)
Definition
qphysxactorbody.cpp:132
QPhysXActorBody::sync
void sync(float deltaTime, QHash< QQuick3DNode *, QMatrix4x4 > &transformCache) override
Definition
qphysxactorbody.cpp:74
QPhysXActorBody::updateFilters
void updateFilters() override
Definition
qphysxactorbody.cpp:235
QPhysXActorBody::getGlobalPose
physx::PxTransform getGlobalPose() override
Definition
qphysxactorbody.cpp:160
QPhysXWorld
Definition
qphysxworld_p.h:33
QPhysXWorld::scene
physx::PxScene * scene
Definition
qphysxworld_p.h:43
QVector3D
The QVector3D class represents a vector or vertex in 3D space.
Definition
qvectornd.h:178
physx
Definition
qphysxactorbody_p.h:22
physx::PxTransform
PxTransformT< float > PxTransform
Definition
qabstractphysicsnode_p.h:28
PHYSX_RELEASE
#define PHYSX_RELEASE(x)
Definition
qabstractphysxnode.cpp:15
getPhysXLocalTransform
static QT_BEGIN_NAMESPACE physx::PxTransform getPhysXLocalTransform(const QQuick3DNode *node)
Definition
qphysxactorbody.cpp:30
QT_BEGIN_NAMESPACE
#define QT_BEGIN_NAMESPACE
Definition
qtconfigmacros.h:161
QT_END_NAMESPACE
#define QT_END_NAMESPACE
Definition
qtconfigmacros.h:162
StaticPhysXObjects
Definition
qstaticphysxobjects_p.h:71
StaticPhysXObjects::getReference
static StaticPhysXObjects & getReference()
Definition
qstaticphysxobjects.cpp:14
StaticPhysXObjects::physics
physx::PxPhysics * physics
Definition
qstaticphysxobjects_p.h:75
qtquick3dphysics
src
quick3dphysics
physxnode
qphysxactorbody.cpp
Generated on
for Qt by
1.18.0