HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RBD_Solver.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  */
7 
8 #ifndef __RBD_Solver__
9 #define __RBD_Solver__
10 
11 #include "RBD_API.h"
12 
13 #include <SIM/SIM_Collider.h>
14 #include <SIM/SIM_Isect.h>
15 #include <SIM/SIM_OptionsUser.h>
16 #include <SIM/SIM_Solver.h>
17 #include <GU/GU_SDF.h>
18 
19 #include "RBD_Object.h"
20 #include "RBD_Utils.h"
21 
22 class SIM_Object;
23 class SIM_Random;
24 class SIM_SDF;
25 class RBD_State;
26 class RBD_ContactGraph;
27 class RBD_ObjectTree;
28 
29 
30 #define RBD_NAME_COLLISIONITERATIONS "collisioniterations"
31 #define RBD_NAME_CONTACTITERATIONS "contactiterations"
32 #define RBD_NAME_SUBCONTACTITERATIONS "subcontactiterations"
33 #define RBD_NAME_SHOCKPROPAGATION "shockpropagation"
34 #define RBD_NAME_USEEDGES "useedges"
35 #define RBD_NAME_FLAGPENETRATION "flagpenetration"
36 #define RBD_NAME_MINIMUMSUBSTEPS "minimumsubsteps"
37 #define RBD_NAME_MAXIMUMSUBSTEPS "maximumsubsteps"
38 #define RBD_NAME_CFLCOND "cflcond"
39 #define RBD_NAME_RESOLVEPENETRATION "resolvepenetration"
40 #define RBD_NAME_GLUEIGNORESRESTING "glueignoresrestingobjects"
41 
42 /// This is a RBD-RBD meta solver. It handles the cases where
43 /// RBD objects have a Mutual affect relationship with each other.
44 class RBD_API RBD_Solver : public SIM_Solver,
45  public SIM_OptionsUser
46 {
47 public:
54  GETSET_DATA_FUNCS_B(RBD_NAME_GLUEIGNORESRESTING, GlueIgnoresRestingObjects);
58 
62 
63  GET_DATA_FUNC_I(RBD_NAME_MINIMUMSUBSTEPS, MinimumSubSteps);
64  GET_DATA_FUNC_I(RBD_NAME_MAXIMUMSUBSTEPS, MaximumSubSteps);
66 
67  /// This is public as we need it in our contact graph builder.
68  bool doObjectsCollide(RBD_Object *obja,
69  RBD_Object *objb,
70  const SIM_Time &time,
71  const SIM_Time &timestep) const;
72 
73  /// This method creates an RBD_ObjectTree of the type requested
74  /// by our cull mode.
75  RBD_ObjectTree *createObjectTree() const;
76 
77  /// Takes the solve info attached to the object, checks to
78  /// see if it was created by us, if so, casts to RBD_Object
79  /// and returns. Can return null if the object wasn't initialized
80  /// or was done with another solver.
81  RBD_Object *convertToRBDObject(const SIM_Object *obj) const;
82 
83  /// This should be kept in sync with the contact group method
84  /// menu.
86  {
87  CONTACTGROUP_NONE = 0,
89  CONTACTGROUP_AVERAGE
90  };
91 
92 protected:
93  explicit RBD_Solver(const SIM_DataFactory *factory);
94  ~RBD_Solver() override;
95 
96  SIM_Result solveObjectsSubclass(SIM_Engine &engine,
97  SIM_ObjectArray &objects,
98  SIM_ObjectArray &newobjects,
99  SIM_ObjectArray &feedbacktoobjects,
100  const SIM_Time &timestep) override;
102  const SIM_Object &object,
103  const UT_Vector3 &impulseworldpos,
104  UT_DMatrix3 &immatrix) const override;
106  const SIM_Object &object,
107  int ptnum,
108  UT_DMatrix3 &immatrix) const override;
110  const UT_Vector3 &worldspacepos,
111  const SIM_Property &property) const override;
113  int ptnum,
114  const SIM_Property &property) const override;
116  const SIM_Object &object,
117  UT_String &label) const override;
119  const SIM_Object &object,
120  const UT_String &colliderlabel,
121  UT_String &collidertype,
122  bool &colliderreverseobjectroles
123  ) const override;
124 
125 private:
126  static const SIM_DopDescription *getSolverRBDDopDescription();
127 
128  /// Get a property value by looking at the RBD_State of an object.
129  fpreal getPropertyFromState(const SIM_Object &object,
130  const SIM_Property &property) const;
131 
132  /// Applies the stacking solver.
133  void solveStackObjects(SIM_ObjectArray &objects,
134  SIM_ObjectArray &newobjects,
135  const SIM_Time &time,
136  const SIM_Time &timestep);
137 
138  // Stack solving methods:
139 
140  /// Creates a SIM_Random data on all the objects in the array. This
141  /// data is used by the stack solver.
142  SIM_Random *createRandomData();
143 
144  /// Resolve contact forces.
145  /// Returns true if any contact forces occurred.
146  bool resolveContactForces(const RBD_ContactGraph &graph,
147  const RBD_ObjectArray &objects,
148  const SIM_Time &time,
149  const SIM_Time &timestep,
150  bool applyshock) const;
151 
152  /// Resolve actual penetration.
153  /// Attempts to jiggle objects so they do not penetrate at all.
154  /// All updates are done purely on position. Penetration ignores
155  /// velocity (so two objects moving apart, but overlapping, will
156  /// be jiggled)
157  /// The contact graph is used to provide a hierarchy for the resolution
158  /// Returns true if any jiggling occurred.
159  bool resolvePenetrations(const RBD_ContactGraph &graph,
160  const UT_ValArray<RBD_Object *> &objects,
161  const SIM_Time &time,
162  const SIM_Time &timestep) const;
163 
164  /// Fixes any penetrations between obj & rest by moving obj so that
165  /// they no longer penetrate. Returns true if any change occurred.
166  /// Restitution is what percentage to move them.
167  bool fixPenetrations(RBD_Object *obj, RBD_Object *rest,
168  const SIM_Collider *collider,
169  fpreal restitution,
170  const SIM_Time time,
171  const SIM_Time timestep) const;
172 
173  /// Resolve elastic object collisions.
174  /// Returns true if there were any elastic collisions.
175  bool resolveElasticCollisions(RBD_ObjectArray &objects,
176  const SIM_Time &time,
177  const SIM_Time &timestep) const;
178 
179  /// Applies forces to all of our pins so as to ensure they
180  /// have no relative velocity.
181  void resolvePinConstraintVelocities(RBD_Object *obj) const;
182 
183  /// Moves all of our pinned objects so they satisfy their
184  /// pin constraints.
185  /// This is done in a shock propagation style manner - a, possibly
186  /// arbitrary, hierarchy is setup and each object is satisfied in
187  /// turn, treating previous objects as locked.
188  void shockPropagatePinConstraints(const RBD_ObjectArray &objects) const;
189 
190  /// Collide two objects elastically. Ignores rest of world,
191  /// applies impulses until each intersecting point is seperating
192  /// at least once.
193  /// infinitemass set to true treats object b as infinite mass,
194  /// even if it actually has finite mass.
195  bool elasticCollide(RBD_Object *obj_a, RBD_Object *obj_b,
196  bool infinitemass,
197  fpreal restitution,
198  bool onlyfirst,
199  bool usebounce,
200  const SIM_Time time,
201  const SIM_Time timestep,
202  const SIM_Collider *collider,
203  SIM_Collider::SIM_ImpactApplyType affectortype) const;
204 
205  /// Extracts the next SIM_Isect from the queue. Uses the contact
206  /// grouping method to merge contacts of similar depth.
207  SIM_Isect *groupContacts(SIM_IsectPriorityQueue &queue,
208  RBD_Object *obj_a,
209  RBD_Object *obj_b,
210  bool infinitemass) const;
211 
212  /// Given a point of intersection, find and apply the impulse
213  /// required to cause the point to be seperating. (If it is
214  /// already seperating, ignore)
215  bool collidePoint(RBD_Object *obj_a, RBD_Object *obj_b,
216  bool infinitemass,
217  const SIM_Isect *isect,
218  fpreal restitution,
219  bool usebounce,
220  const SIM_Time curtime,
221  bool usesdfvel,
222  bool usepointvel,
223  int child_id_a = -1,
224  int child_id_b = -1) const;
225 
226  /// Determines the possible frozen sub object that is closest
227  /// to the given point in the SDF sense.
228  /// Returns true if a new closest child is found.
229  /// If onlytoplevel is true, the only possible objects returned
230  /// are the original obj or its children. Subobjects are still
231  /// tested, but their respective parent inherits ownership.
232  bool findClosestChild(RBD_Object *obj,
233  const UT_Vector3 &pos,
234  RBD_Object *&closest, fpreal &mindist,
235  bool onlytoplevel = false,
236  int child_id = -1) const;
237 
238  /// Given an impulse and position, applies the impulse to the
239  /// object. This is used for collision impulses. The idea is
240  /// that by sending them through this interface we can track
241  /// what impulses have been applied to the object.
242  /// The opposite impulse will be sent to object b, if it is given.
243  /// restingcollision is set if this is a result of objects resting
244  /// on each other rather than elastically colliding.
245  void applyCollisionImpulse(RBD_Object *obj_a,
246  RBD_Object *obj_b,
247  int obj_b_id,
248  fpreal scale,
249  const UT_Vector3 &pos,
250  const UT_Vector3 &impulse,
251  const SIM_Time curtime,
252  int child_id_a,
253  int child_id_b,
254  bool infiniteforceVSinfinitemass,
255  bool restingcollision) const;
256 
257  /// Adds the given impact to the SIM_Impact list for the given
258  /// pair of objects.
259  /// The given impulse vector does not have to be normalized.
260  void addImpactData(RBD_Object *obj_a,
261  RBD_Object *obj_b,
262  int obj_b_id,
263  const UT_Vector3 &pos,
264  const UT_Vector3 &nml,
265  fpreal strength,
266  const SIM_Time curtime,
267  bool restingcollision) const;
268 
269  /// Collide two objects using the collideObjects() from the collider
270  bool collideObjects (RBD_Object *obj_a, RBD_Object *obj_b,
271  const SIM_Time startTime,
272  const SIM_Time endTime,
273  SIM_Collider::SIM_ImpactApplyType affectortype) const;
274 
275  SIM_Time getCurSolveTime() const
276  { return myCurSolveTime; }
277  void setCurSolveTime(SIM_Time time)
278  { myCurSolveTime = time; }
279  SIM_Time getCurSolveStep() const
280  { return myCurSolveStep; }
281  void setCurSolveStep(SIM_Time step)
282  { myCurSolveStep = step; }
283 
284  bool doAddImpacts() const
285  { return myAddImpacts; }
286  bool doGlueIgnoresResting() const
287  { return myGlueIgnoresResting; }
288 
291  SIM_Solver,
292  "RBD Solver",
293  getSolverRBDDopDescription());
294 
295 private:
296  // Flag variables used during the simulation
297 
298  /// Flags if anything broke during the simulation. Lets us know
299  /// we need to rebuild topology dependent constructs.
300  mutable bool myBreakOccurred;
301 
302  /// Determins if we should add SIM_Impact data for every
303  /// collision we process.
304  /// This is done to avoid possibly expensive parameter evaluation
305  /// in deeply nested functions.
306  mutable bool myAddImpacts;
307  mutable bool myGlueIgnoresResting;
308 
309  /// Current solve time.
310  SIM_Time myCurSolveTime;
311  SIM_Time myCurSolveStep;
312 
313  SIM_Engine *myEngine;
314 };
315 
316 #endif
317 
#define DECLARE_STANDARD_GETCASTTOTYPE()
Definition: SIM_DataUtils.h:45
#define RBD_NAME_RESOLVEPENETRATION
Definition: RBD_Solver.h:39
This class defines various types of collisions.
Definition: SIM_Isect.h:18
GLenum GLenum GLenum GLenum GLenum scale
Definition: glew.h:14163
#define GETSET_DATA_FUNCS_B(DataName, FuncName)
GT_API const UT_StringHolder time
virtual void getDefaultColliderSubclass(const SIM_Object &object, const UT_String &colliderlabel, UT_String &collidertype, bool &colliderreverseobjectroles) const
#define RBD_NAME_SHOCKPROPAGATION
Definition: RBD_Solver.h:33
#define RBD_API
Definition: RBD_API.h:10
#define GETSET_DATA_FUNCS_F(DataName, FuncName)
#define DECLARE_DATAFACTORY(DataClass, SuperClass, Description, DopParms)
Definition: SIM_DataUtils.h:58
#define RBD_NAME_CFLCOND
Definition: RBD_Solver.h:38
rbdContactGroupMethod
Definition: RBD_Solver.h:85
#define GET_DATA_FUNC_I(DataName, FuncName)
#define RBD_NAME_SUBCONTACTITERATIONS
Definition: RBD_Solver.h:32
SIM_ImpactApplyType
Defines the possible affector types when doing collision detection.
Definition: SIM_Collider.h:56
#define RBD_NAME_COLLISIONITERATIONS
Definition: RBD_Solver.h:30
Holds pointers to a number of SIM_Object objects.
This class holds a signed distance function representing a GU_Detail.
Definition: SIM_SDF.h:27
GLhandleARB obj
Definition: glew.h:6266
INT property
Definition: wglew.h:145
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:2544
virtual void getImpulseMassMatrixSubclass(const SIM_Object &object, const UT_Vector3 &impulseworldpos, UT_DMatrix3 &immatrix) const
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the queue
Definition: thread.h:629
#define GETSET_DATA_FUNCS_I(DataName, FuncName)
virtual SIM_Result solveObjectsSubclass(SIM_Engine &engine, SIM_ObjectArray &objects, SIM_ObjectArray &newobjects, SIM_ObjectArray &feedbacktoobjects, const SIM_Time &timestep)=0
virtual fpreal getPropertyAtPositionSubclass(const SIM_Object &object, const UT_Vector3 &worldpos, const SIM_Property &property) const
#define RBD_NAME_MAXIMUMSUBSTEPS
Definition: RBD_Solver.h:37
virtual void getDefaultColliderLabelSubclass(const SIM_Object &object, UT_String &label) const
Gets the default collider label for an object using this solver.
#define RBD_NAME_CONTACTGROUPMETHOD
Definition: RBD_Utils.h:36
#define RBD_NAME_CONTACTGROUPTOL
Definition: RBD_Utils.h:37
fpreal64 fpreal
Definition: SYS_Types.h:277
#define RBD_NAME_ADDIMPACTS
Definition: RBD_Utils.h:35
#define RBD_NAME_MINIMUMSUBSTEPS
Definition: RBD_Solver.h:36
#define RBD_NAME_USEPOINTVELOCITY
Definition: RBD_Utils.h:27
#define GET_DATA_FUNC_F(DataName, FuncName)
#define RBD_NAME_CULLMODE
Definition: RBD_Utils.h:34
#define RBD_NAME_USESDFVELOCITY
Definition: RBD_Utils.h:28
#define RBD_NAME_FLAGPENETRATION
Definition: RBD_Solver.h:35
#define RBD_NAME_GLUEIGNORESRESTING
Definition: RBD_Solver.h:40
virtual void getPointImpulseMassMatrixSubclass(const SIM_Object &object, int ptnum, UT_DMatrix3 &immatrix) const
GA_API const UT_StringHolder rest
SIM_Property
virtual fpreal getPropertyAtPointSubclass(const SIM_Object &object, int ptnum, const SIM_Property &property) const
#define RBD_NAME_CONTACTITERATIONS
Definition: RBD_Solver.h:31