HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RBD_Object.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: RBD_Object.h ( RBD Library, C++)
7  *
8  * COMMENTS:
9  * This holds all the data we care about for RBD Objects
10  * This allows us to avoid having to re-acquire the data
11  * in innermost loops.
12  */
13 
14 #ifndef __RBD_Object_H__
15 #define __RBD_Object_H__
16 
17 #include "RBD_API.h"
18 #include <UT/UT_Vector3.h>
19 #include <UT/UT_BoundingBox.h>
20 #include <UT/UT_Map.h>
21 #include <UT/UT_Quaternion.h>
22 #include <UT/UT_TokenString.h>
23 #include <UT/UT_ValArray.h>
24 #include <UT/UT_Vector3Array.h>
25 #include <SIM/SIM_ObjectArray.h>
26 #include <SIM/SIM_Solver.h>
27 #include <SIM/SIM_Collider.h>
29 #include <GU/GU_SDF.h>
30 #include "RBD_SharedAffectorList.h"
31 
32 class SIM_Object;
33 class SIM_Geometry;
34 class SIM_Engine;
35 class SIM_Time;
36 class SIM_SDF;
37 class SIM_Impacts;
39 class RBD_Object;
40 class RBD_Solver;
41 class RBD_State;
42 class RBD_SphereTree;
45 
47 
49 {
50 public:
51  RBD_Object(const SIM_Solver *solver, SIM_Object *obj);
52  ~RBD_Object() override;
53 
54  /// These cache the common RBD structures so we don't have
55  /// to look them up every time we fetch them.
56  SIM_Object *getObject() const { return myObject; }
57  RBD_State *getState() const { return myState; }
58  SIM_Impacts *getImpacts();
59  const SIM_SDF *getSDF() const { return mySDF; }
60  const SIM_Geometry *getGeometry() const { return myGeometry; }
61 
62  const RBD_SphereTree*getSphereTree() const;
63 
64  /// This is the radius of this object from the pivot position.
65  /// It is thus orientation independent.
66  fpreal getRadius() const { return myRadius; }
67 
68  /// Returns true if this object can intersect anywhere in space
69  /// Used for things like implicit planes.
70  bool isInfiniteExtent() const;
71 
72  /// This returns the bounding box of the object inside it's
73  /// own frame. This must be transformed by the orientation
74  /// to get the world bounding box.
75  void getBBox(UT_BoundingBox &bbox) const;
76 
77  /// Accumulates into the given arrays all of our point's positions
78  /// and velocities. Both are given in world space.
79  void accumulatePointVelocity(UT_Vector3Array &pos,
80  UT_Vector3Array &vel) const;
81 
82  /// Stashes the current state internally.
83  void stashState();
84 
85  /// Reloads our impact data structure from the SIM_Object. This must
86  /// be done whenever preserveImpacts is called.
87  void reloadImpacts(
88  SIM_Collider::SIM_ImpactApplyType impactaplytype);
89 
90  /// Copies our NewImpact data into Impacts.
91  /// This is a pass through to SIM_Object, but ensures our cached
92  /// impact structure is cleared.
93  void preserveImpacts(SIM_Engine *engine);
94 
95  /// Restores the position of the state using changePosition.
96  void restoreStatePos();
97  /// Restores the velocity of the state using changeVelocity.
98  void restoreStateVel();
99  /// Restores the full state
100  void restoreState();
101 
102  /// This returns a list of all the objects that are frozen to us.
103  void getGlueSubObjects(RBD_ObjectArray &objlist) const;
104 
105  /// Discover the number of glued subobjects and retrieve a specific
106  /// one
107  int getNumGlueSubObjects() const;
108  RBD_Object *getNthGlueSubObject(int i) const;
109 
110  /// Returns our parent object, null if not glued.
111  RBD_Object *getGlueParent() const { return myGlueParent; }
112 
113  /// This returns true if we have any frozen sub objects.
114  bool hasGlueSubObjects() const;
115 
116  /// Marks that obj is glued to this.
117  void addGlueSubObject(RBD_Object *obj);
118 
119  /// Removes that object as being glued to this.
120  void removeGlueSubObject(RBD_Object *obj);
121 
122  /// Returns true if the given object is one of our glue children.
123  bool hasAsGlueChild(RBD_Object *obj);
124 
125  /// Return if this object is glued to somewhere else.
126  bool isGlued() const { return myIsGlued; }
127 
128  /// Builds the impulse model matrix for the given
129  /// world space coordinate. This matrix when multiplied by
130  /// an impulse will give the change in velocity at that point
131  /// caused by the impulse.
132  ///
133  /// This takes hard constraints into consideration.
134  /// Builds the impulse model matrix describing the velocity change
135  /// at point p given a force at point f.
136  /// This is Mfp-1 in my naming scheme.
137  void buildImpulseModel(UT_DMatrix3 &k,
138  const UT_Vector3 &f,
139  const UT_Vector3 &p) const;
140 
141  /// Builds the impulse model matrix describing motion of P on *this
142  /// given an a force at f on *this.
143  /// This is Mzfp-1(A) in my naming scheme, where this is Z.
144  void buildImpulseModelForA(UT_DMatrix3 &k,
145  const UT_Vector3 &f,
146  const UT_Vector3 &p,
147  RBD_Object *A) const;
148 
149  /// Determines what hard constraints are present at this time
150  /// step and updates its internal model to reflect theses.
151  /// We need the end time to be able to acquire non-interpolated
152  /// objects to handle live pin constraints.
153  void buildConstraints(const RBD_Solver *solver,
154  const SIM_Time &time,
155  const SIM_Time &endtime);
156 
157  /// Removes the constraints added. This restores stuff like the
158  /// pivot to its original value.
159  void removeConstraints();
160 
161  /// Applies an impulse to this object.
162  /// This results in an instantaneous change in velocity and
163  /// angular velocity.
164  void applyImpulse(const UT_Vector3 &pos,
165  fpreal impulse,
166  const UT_Vector3 &normal);
167  /// Applies impulses from SIM_Impacts data.
168  void applyImpacts(const SIM_Impacts *impacts,
169  const SIM_Time &time,
170  const SIM_Time &timestep);
171 
172  /// Integrate position. Uses current velocity.
173  void integratePosition(const SIM_Time &time,
174  const SIM_Time &timestep);
175 
176  /// Integrate velocity. Finds & applies all forces.
177  void integrateVelocity(const SIM_Time &time,
178  const SIM_Time &timestep);
179 
180  /// Builds the SDF and updates the state from the sdf,
181  /// unless sdf is already built.
182  void initSDF();
183 
184  /// Updates the state from geometry, unless already calculated.
185  void initFromGeometry();
186 
187  /// Calculates the radius, unless already calculated.
188  void initRadius();
189 
190  /// Calculates the bounding box.
191  void initBBox(bool useSDF);
192 
193  /// Gathers all of our builder requests.
194  void gatherBuilderRequests(UT_Array<GU_SDFDelayedBuilder> &buildrequests);
195 
196  /// Initialize for collisions
197  void initForCollisions();
198 
199  /// Calculates the property value at the given world position.
200  fpreal getPropertyAtPosition(
201  const SIM_Property &property,
202  const UT_Vector3 &pos) const;
203 
204  /// Rebuilds the list of affectors for this object.
205  /// Interpolates the affectors for the given time.
206  void rebuildAffectorList(const RBD_Solver *solver,
207  SIM_Engine &engine,
208  const SIM_Time &time,
209  const SIM_Time &timestep,
210  RBD_SharedAffectorListArray &affectorlists,
212 
213  /// Gets the transform matrix from self to world from stashed state
214  void getStashedTransform(UT_DMatrix4 &xform) const;
215 
216  void findOverlapIdx(const RBD_Solver *solver,
217  UT_IntArray &overlap)
218  { if( mySharedAffectorList )
219  mySharedAffectorList->findOverlapIdx(solver,
220  this,
221  overlap);
222  else
223  overlap.entries(0); }
225  { if( mySharedAffectorList )
226  mySharedAffectorList->setObjectTreeDirty(); }
227 
228  int getNumAffectors() const
229  { return mySharedAffectorList
230  ? mySharedAffectorList->entries()
231  : 0; }
233  { return (*mySharedAffectorList)(j); }
234  const SIM_Collider *getCollider(int j, const char *defaultlabel) const
235  { return mySharedAffectorList->
236  getCollider(j, myObject, defaultlabel); }
238  { return mySharedAffectorList->getImpactApplyType(j); }
239 
240  // The array index value is used by the solver to keep track of the
241  // RBD_Object's position within an array. It is a temporary value with
242  // meaning only for the solver.
243  int getArrayIndex() const
244  { return myArrayIndex; }
246  { myArrayIndex = index; }
247 
248  bool hasNailConstraints() const
249  { return myHasConstraints; }
250 
252  void clearCollideCache();
253 
254  void cachePhysicalValues();
255  void restorePhysicalValues();
256 
257  // Are we currently processing pin constraints for this object?
258  mutable bool myPinProcessFlag;
260 
261  // This is the position of the anchors. It is stored in
262  // our object space of this for AnchorPos and of myPinObjects for
263  // goal pos.
266 
267 protected:
268  // Iterates over all constraints attached to piece. All hard
269  // constraints are added to our own list of pin constraints
270  // and our list of hard positions.
271  // Recurses to all glued subobjects.
272  void accumulateConstraints(const RBD_Solver *solver,
273  RBD_Object *piece,
274  UT_Vector3Array &hard_objpos,
275  UT_Vector3Array &hard_goalpos,
276  UT_Matrix3 &hard_spatialfilter,
277  UT_Matrix3 &hard_rotationalfilter,
278  const SIM_Time &time,
279  const SIM_Time &endtime);
280 
281 private:
282  /// Gets the property for a specific position by trying to find
283  /// the closest point to that position. The closest point will
284  /// then return it's attribute value (if any) or the rbd state
285  /// corresponding to that.
286  /// This recurses down the glue hierarchy.
287  void findClosestPropertyAtPosition(fpreal &newvalue,
288  const SIM_Property &property,
289  const UT_Vector3 &pos,
290  bool &found, fpreal &closestdist) const;
291 
292  SIM_Object *myObject;
293  RBD_State *myState;
294  SIM_Impacts *myImpacts;
295  RBD_SharedAffectorList *mySharedAffectorList;
296  int myArrayIndex;
297 
298  const SIM_Geometry *myGeometry;
299  const SIM_SDF *mySDF;
300 
301  // Stashes whether we have these attributes & what their
302  // offsets are.
303  mutable GA_ROAttributeRef myPropertyOffset[SIM_PROPERTY_COUNT];
304  mutable bool myPropertyLookedUp[SIM_PROPERTY_COUNT];
305  mutable const RBD_SphereTree *mySphereTree;
306 
307  // Our radius, -1 if not yet computed.
308  fpreal myRadius;
309 
310  // Our bounding box, in local coords.
311  bool myBBoxValid;
312  UT_BoundingBox myBBox;
313 
314  // This is where we stash our orientation.
315  UT_Vector3 myStashPos;
316  UT_Quaternion myStashOrient;
317  UT_Vector3 myStashVel;
318  UT_Vector3 myStashAngVel;
319 
320  // Something glued will not simulate.
321  bool myIsGlued;
322  // Stores if we have constraints.
323  bool myHasConstraints;
324 
325  // Pre-constraint values for these.
326  UT_Matrix3 myCacheTensor;
327  UT_Vector3 myCachePivot;
328  UT_Vector3 myMomentArm;
329  UT_Matrix3 mySpatialFilter;
330  UT_Matrix3 myRotationalFilter;
331 
332  // This is used temporarily during the solving process to track
333  // what subobjects are present.
334  RBD_Object *myGlueParent;
335  RBD_ObjectArray myGlueSubObjects;
336 
337  // Cached physical properties of standalone RBD Object (excludes glued
338  // children).
339  bool myHasCachedPhysicalValues;
340  fpreal myCachedMass;
341  UT_Vector3 myCachedCenterOfMass;
342  UT_DMatrix3 myCachedInertialTensor;
343 
345 
346  bool myHasInitFromGeometry;
347 };
348 
349 #endif
SIM_Object * getObject() const
Definition: RBD_Object.h:56
UT_Vector3Array myPinAnchorPos
Definition: RBD_Object.h:264
int getArrayIndex() const
Definition: RBD_Object.h:243
GT_API const UT_StringHolder time
UT_Vector3Array myPinAnchorGoalPos
Definition: RBD_Object.h:265
int getNumAffectors() const
Definition: RBD_Object.h:228
#define RBD_API
Definition: RBD_API.h:10
const SIM_Collider * getCollider(int j, const char *defaultlabel) const
Definition: RBD_Object.h:234
RBD_ObjectArray myPinObjects
Definition: RBD_Object.h:259
fpreal getRadius() const
Definition: RBD_Object.h:66
void setAffectorTreeDirty()
Definition: RBD_Object.h:224
GLfloat f
Definition: glcorearb.h:1926
const SIM_Geometry * getGeometry() const
Definition: RBD_Object.h:60
const SIM_SDF * getSDF() const
Definition: RBD_Object.h:59
This class provides a way to manage a reference to an attribute permitting Read-Only access...
SIM_ImpactApplyType
Defines the possible affector types when doing collision detection.
Definition: SIM_Collider.h:56
This class holds a signed distance function representing a GU_Detail.
Definition: SIM_SDF.h:27
UT_ValArray< RBD_Object * > RBD_ObjectArray
Definition: RBD_Object.h:44
void setArrayIndex(int index)
Definition: RBD_Object.h:245
RBD_Object * getAffector(int j) const
Definition: RBD_Object.h:232
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:648
GLint j
Definition: glad.h:2733
UT_ValArray< SIM_ColliderCacheData * > & getCollideCache()
Definition: RBD_Object.h:251
SIM_Collider::SIM_ImpactApplyType getImpactApplyType(int j) const
Definition: RBD_Object.h:237
fpreal64 fpreal
Definition: SYS_Types.h:277
GLuint index
Definition: glcorearb.h:786
bool hasNailConstraints() const
Definition: RBD_Object.h:248
RBD_State * getState() const
Definition: RBD_Object.h:57
void findOverlapIdx(const RBD_Solver *solver, UT_IntArray &overlap)
Definition: RBD_Object.h:216
RBD_Object * getGlueParent() const
Returns our parent object, null if not glued.
Definition: RBD_Object.h:111
bool myPinProcessFlag
Definition: RBD_Object.h:258
SIM_Property
bool isGlued() const
Return if this object is glued to somewhere else.
Definition: RBD_Object.h:126