HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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  virtual ~RBD_Solver();
95 
96  virtual SIM_Result solveObjectsSubclass(SIM_Engine &engine,
97  SIM_ObjectArray &objects,
98  SIM_ObjectArray &newobjects,
99  SIM_ObjectArray &feedbacktoobjects,
100  const SIM_Time &timestep);
101  virtual void getImpulseMassMatrixSubclass(
102  const SIM_Object &object,
103  const UT_Vector3 &impulseworldpos,
104  UT_DMatrix3 &immatrix) const;
106  const SIM_Object &object,
107  int ptnum, UT_DMatrix3 &immatrix) const;
108  virtual fpreal getPropertyAtPositionSubclass(const SIM_Object &object,
109  const UT_Vector3 &worldspacepos,
110  const SIM_Property &property) const;
111  virtual fpreal getPropertyAtPointSubclass(const SIM_Object &object,
112  int ptnum, const SIM_Property &property) const;
113  virtual void getDefaultColliderLabelSubclass(
114  const SIM_Object &object,
115  UT_String &label) const;
116  virtual void getDefaultColliderSubclass(
117  const SIM_Object &object,
118  const UT_String &colliderlabel,
119  UT_String &collidertype,
120  bool &colliderreverseobjectroles) const;
121 
122 private:
123  static const SIM_DopDescription *getSolverRBDDopDescription();
124 
125  /// Get a property value by looking at the RBD_State of an object.
126  fpreal getPropertyFromState(const SIM_Object &object,
127  const SIM_Property &property) const;
128 
129  /// Applies the stacking solver.
130  void solveStackObjects(SIM_ObjectArray &objects,
131  SIM_ObjectArray &newobjects,
132  const SIM_Time &time,
133  const SIM_Time &timestep);
134 
135  // Stack solving methods:
136 
137  /// Creates a SIM_Random data on all the objects in the array. This
138  /// data is used by the stack solver.
139  SIM_Random *createRandomData();
140 
141  /// Resolve contact forces.
142  /// Returns true if any contact forces occurred.
143  bool resolveContactForces(const RBD_ContactGraph &graph,
144  const RBD_ObjectArray &objects,
145  const SIM_Time &time,
146  const SIM_Time &timestep,
147  bool applyshock) const;
148 
149  /// Resolve actual penetration.
150  /// Attempts to jiggle objects so they do not penetrate at all.
151  /// All updates are done purely on position. Penetration ignores
152  /// velocity (so two objects moving apart, but overlapping, will
153  /// be jiggled)
154  /// The contact graph is used to provide a hierarchy for the resolution
155  /// Returns true if any jiggling occurred.
156  bool resolvePenetrations(const RBD_ContactGraph &graph,
157  const UT_ValArray<RBD_Object *> &objects,
158  const SIM_Time &time,
159  const SIM_Time &timestep) const;
160 
161  /// Fixes any penetrations between obj & rest by moving obj so that
162  /// they no longer penetrate. Returns true if any change occurred.
163  /// Restitution is what percentage to move them.
164  bool fixPenetrations(RBD_Object *obj, RBD_Object *rest,
165  const SIM_Collider *collider,
166  fpreal restitution,
167  const SIM_Time time,
168  const SIM_Time timestep) const;
169 
170  /// Resolve elastic object collisions.
171  /// Returns true if there were any elastic collisions.
172  bool resolveElasticCollisions(RBD_ObjectArray &objects,
173  const SIM_Time &time,
174  const SIM_Time &timestep) const;
175 
176  /// Applies forces to all of our pins so as to ensure they
177  /// have no relative velocity.
178  void resolvePinConstraintVelocities(RBD_Object *obj) const;
179 
180  /// Moves all of our pinned objects so they satisfy their
181  /// pin constraints.
182  /// This is done in a shock propagation style manner - a, possibly
183  /// arbitrary, hierarchy is setup and each object is satisfied in
184  /// turn, treating previous objects as locked.
185  void shockPropagatePinConstraints(const RBD_ObjectArray &objects) const;
186 
187  /// Collide two objects elastically. Ignores rest of world,
188  /// applies impulses until each intersecting point is seperating
189  /// at least once.
190  /// infinitemass set to true treats object b as infinite mass,
191  /// even if it actually has finite mass.
192  bool elasticCollide(RBD_Object *obj_a, RBD_Object *obj_b,
193  bool infinitemass,
194  fpreal restitution,
195  bool onlyfirst,
196  bool usebounce,
197  const SIM_Time time,
198  const SIM_Time timestep,
199  const SIM_Collider *collider,
200  SIM_Collider::SIM_ImpactApplyType affectortype) const;
201 
202  /// Extracts the next SIM_Isect from the queue. Uses the contact
203  /// grouping method to merge contacts of similar depth.
204  SIM_Isect *groupContacts(SIM_IsectPriorityQueue &queue,
205  RBD_Object *obj_a,
206  RBD_Object *obj_b,
207  bool infinitemass) const;
208 
209  /// Given a point of intersection, find and apply the impulse
210  /// required to cause the point to be seperating. (If it is
211  /// already seperating, ignore)
212  bool collidePoint(RBD_Object *obj_a, RBD_Object *obj_b,
213  bool infinitemass,
214  const SIM_Isect *isect,
215  fpreal restitution,
216  bool usebounce,
217  const SIM_Time curtime,
218  bool usesdfvel,
219  bool usepointvel,
220  int child_id_a = -1,
221  int child_id_b = -1) const;
222 
223  /// Determines the possible frozen sub object that is closest
224  /// to the given point in the SDF sense.
225  /// Returns true if a new closest child is found.
226  /// If onlytoplevel is true, the only possible objects returned
227  /// are the original obj or its children. Subobjects are still
228  /// tested, but their respective parent inherits ownership.
229  bool findClosestChild(RBD_Object *obj,
230  const UT_Vector3 &pos,
231  RBD_Object *&closest, fpreal &mindist,
232  bool onlytoplevel = false,
233  int child_id = -1) const;
234 
235  /// Given an impulse and position, applies the impulse to the
236  /// object. This is used for collision impulses. The idea is
237  /// that by sending them through this interface we can track
238  /// what impulses have been applied to the object.
239  /// The opposite impulse will be sent to object b, if it is given.
240  /// restingcollision is set if this is a result of objects resting
241  /// on each other rather than elastically colliding.
242  void applyCollisionImpulse(RBD_Object *obj_a,
243  RBD_Object *obj_b,
244  int obj_b_id,
245  fpreal scale,
246  const UT_Vector3 &pos,
247  const UT_Vector3 &impulse,
248  const SIM_Time curtime,
249  int child_id_a,
250  int child_id_b,
251  bool infiniteforceVSinfinitemass,
252  bool restingcollision) const;
253 
254  /// Adds the given impact to the SIM_Impact list for the given
255  /// pair of objects.
256  /// The given impulse vector does not have to be normalized.
257  void addImpactData(RBD_Object *obj_a,
258  RBD_Object *obj_b,
259  int obj_b_id,
260  const UT_Vector3 &pos,
261  const UT_Vector3 &nml,
262  fpreal strength,
263  const SIM_Time curtime,
264  bool restingcollision) const;
265 
266  /// Collide two objects using the collideObjects() from the collider
267  bool collideObjects (RBD_Object *obj_a, RBD_Object *obj_b,
268  const SIM_Time startTime,
269  const SIM_Time endTime,
270  SIM_Collider::SIM_ImpactApplyType affectortype) const;
271 
272  SIM_Time getCurSolveTime() const
273  { return myCurSolveTime; }
274  void setCurSolveTime(SIM_Time time)
275  { myCurSolveTime = time; }
276  SIM_Time getCurSolveStep() const
277  { return myCurSolveStep; }
278  void setCurSolveStep(SIM_Time step)
279  { myCurSolveStep = step; }
280 
281  bool doAddImpacts() const
282  { return myAddImpacts; }
283  bool doGlueIgnoresResting() const
284  { return myGlueIgnoresResting; }
285 
288  SIM_Solver,
289  "RBD Solver",
290  getSolverRBDDopDescription());
291 
292 private:
293  // Flag variables used during the simulation
294 
295  /// Flags if anything broke during the simulation. Lets us know
296  /// we need to rebuild topology dependent constructs.
297  mutable bool myBreakOccurred;
298 
299  /// Determins if we should add SIM_Impact data for every
300  /// collision we process.
301  /// This is done to avoid possibly expensive parameter evaluation
302  /// in deeply nested functions.
303  mutable bool myAddImpacts;
304  mutable bool myGlueIgnoresResting;
305 
306  /// Current solve time.
307  SIM_Time myCurSolveTime;
308  SIM_Time myCurSolveStep;
309 
310  SIM_Engine *myEngine;
311 };
312 
313 #endif
314 
#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
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:2544
#define GETSET_DATA_FUNCS_B(DataName, FuncName)
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)
3D Vector class.
#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
GA_API const UT_StringHolder scale
#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
virtual void getImpulseMassMatrixSubclass(const SIM_Object &object, const UT_Vector3 &impulseworldpos, UT_DMatrix3 &immatrix) const
#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.
double fpreal
Definition: SYS_Types.h:269
#define RBD_NAME_CONTACTGROUPMETHOD
Definition: RBD_Utils.h:36
#define RBD_NAME_CONTACTGROUPTOL
Definition: RBD_Utils.h:37
#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