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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
// This code contains NVIDIA Confidential Information and is disclosed to you
// under a form of NVIDIA software license agreement provided separately to you.
//
// Notice
// NVIDIA Corporation and its licensors retain all intellectual property and
// proprietary rights in and to this software and related documentation and
// any modifications thereto. Any use, reproduction, disclosure, or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA Corporation is strictly prohibited.
//
// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Information and code furnished is believed to be accurate and reliable.
// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
// information or for any infringement of patents or other rights of third parties that may
// result from its use. No license is granted by implication or otherwise under any patent
// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
// This code supersedes and replaces all information previously supplied.
// NVIDIA Corporation products are not authorized for use as critical
// components in life support devices or systems without express written approval of
// NVIDIA Corporation.
//
// Copyright (c) 2008-2017 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PX_PHYSICS_SCP_CONSTRAINT_GROUP_NODE
#define PX_PHYSICS_SCP_CONSTRAINT_GROUP_NODE
#include "ScConstraintProjectionTree.h"
#include "PsUtilities.h" // for Ps::to8()
namespace physx
{
namespace Sc
{
class ConstraintSim;
class BodySim;
class ConstraintProjectionManager;
// A 'simulation island' of constraints. Created by a union-find algorithm every time a new constraint is added to any of the involved bodies.
struct ConstraintGroupNode : public Ps::UserAllocated
{
enum StateFlags
{
eDISCOVERED = 1 << 0, // Used during projection tree generation to mark processed nodes.
eIN_PROJECTION_PASS_LIST = 1 << 1, // Temporarily used to avoid duplicate entries in the list of nodes that should project the pose after the solver
ePENDING_TREE_UPDATE = 1 << 2, // Marks the constraint groups that need their projection trees updated. Must only be set on the root group node.
eNEXT_FREE_SHIFT = 3,
eNEXT_FREE = 1 << eNEXT_FREE_SHIFT
};
// these flags should give a rough hint how many projecting constraints to expect in the constraint group. This will be used for
// load balancing when running projection in parallel. The intervals were chosen somewhat arbitrarily but the general motivation was
// to cover very simple constraint setups, simple ragdolls, complex ragdolls and very complex projection setups. Note that the load
// balancing is not waterproof since at the end it is the projection shader from the external constraint implementer (for example, a joint)
// which decides based on some thresholds whether projection runs or not.
enum ProjectionCountHintFlags
{
e1_TO_4 = eNEXT_FREE,
e5_TO_16 = eNEXT_FREE << 1,
e17_TO_64 = eNEXT_FREE << 2,
e65_TO_INF = eNEXT_FREE << 3,
eCLEAR_MASK = ~(0xffffffff << eNEXT_FREE_SHIFT)
};
ConstraintGroupNode(BodySim& b);
~ConstraintGroupNode()
{
PX_ASSERT(!readFlag(ePENDING_TREE_UPDATE));
PX_ASSERT(projectionFirstRoot == NULL);
}
PX_FORCE_INLINE void raiseFlag(StateFlags f) { flags |= f; }
PX_FORCE_INLINE void clearFlag(StateFlags f) { flags &= ~f; }
PX_FORCE_INLINE bool readFlag(StateFlags f) const { return (flags & f) != 0; }
PX_FORCE_INLINE PxU32 getProjectionCountHint() const;
PX_FORCE_INLINE void setProjectionCountHint(PxU32 constraintsToProjectCount);
ConstraintGroupNode& getRoot();
PX_FORCE_INLINE void buildProjectionTrees(); //build the projection trees for a constraint group.
void markForProjectionTreeRebuild(ConstraintProjectionManager&);
PX_FORCE_INLINE void purgeProjectionTrees();
PX_FORCE_INLINE bool hasProjectionTreeRoot() { return projectionFirstRoot != NULL; }
PX_FORCE_INLINE void setProjectionTreeRoot(ConstraintGroupNode* root) { projectionFirstRoot = root; }
void initProjectionData(ConstraintGroupNode* parent, ConstraintSim* c);
void clearProjectionData();
static void projectPose(ConstraintGroupNode& root, Ps::Array<BodySim*>& projectedBodies);
BodySim* body; //the owner body of this node
//tree for union/find:
ConstraintGroupNode* parent;
ConstraintGroupNode* tail; //only valid if this is root of group, points to LList tail node.
PxU32 rank; //rank counter for union/find. Initially zero. Is number of hops from root to furthest leaf in tree. This is just a hint to create more balanced trees.
//linked list for traversal:
ConstraintGroupNode* next; //next in list, NULL at tail.
//projection tree information
ConstraintGroupNode* projectionFirstRoot; //pointer to first projection tree root node. Only set for constraint group roots
ConstraintGroupNode* projectionNextRoot; //pointer to next projection root node. Only set for constraint group roots
//a constraint group can consist of multiple projection trees if kinematics are involved! Because a kinematic doesn't split
//the constraint group as a static anchor does.
ConstraintGroupNode* projectionParent; //node to project to
ConstraintGroupNode* projectionFirstChild; //first node which gets projected to this one
ConstraintGroupNode* projectionNextSibling; //the next sibling which gets projected to the same node as this one. NULL if projectionParent is NULL.
ConstraintSim* projectionConstraint; //the constraint to project (constraint to projection parent)
private:
PxU8 flags;
};
} // namespace Sc
PX_FORCE_INLINE PxU32 Sc::ConstraintGroupNode::getProjectionCountHint() const
{
// return the mean of the upper and lower bound
if (flags & ConstraintGroupNode::e65_TO_INF)
return 128;
else if (flags & ConstraintGroupNode::e17_TO_64)
return 40;
else if (flags & ConstraintGroupNode::e5_TO_16)
return 10;
else if (flags & ConstraintGroupNode::e1_TO_4)
return 2;
return 0;
}
PX_FORCE_INLINE void Sc::ConstraintGroupNode::setProjectionCountHint(PxU32 constraintsToProjectCount)
{
PxU8 tmpFlags = flags;
tmpFlags &= PxU8(ConstraintGroupNode::eCLEAR_MASK);
if (constraintsToProjectCount >= 65)
tmpFlags |= ConstraintGroupNode::e65_TO_INF;
else if (constraintsToProjectCount >= 17)
tmpFlags |= ConstraintGroupNode::e17_TO_64;
else if (constraintsToProjectCount >= 5)
tmpFlags |= ConstraintGroupNode::e5_TO_16;
else if (constraintsToProjectCount >= 1)
tmpFlags |= ConstraintGroupNode::e1_TO_4;
flags = tmpFlags;
}
PX_FORCE_INLINE void Sc::ConstraintGroupNode::buildProjectionTrees()
{
PX_ASSERT(this == parent); // Only call for group roots
PX_ASSERT(!hasProjectionTreeRoot());
ConstraintProjectionTree::buildProjectionTrees(*this);
}
PX_FORCE_INLINE void Sc::ConstraintGroupNode::purgeProjectionTrees()
{
PX_ASSERT(this == parent); // Only call for group roots
PX_ASSERT(hasProjectionTreeRoot());
ConstraintProjectionTree::purgeProjectionTrees(*this);
}
}
#endif
|