HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SIM_Force.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 __SIM_Force_h__
9 #define __SIM_Force_h__
10 
11 #include "SIM_API.h"
12 #include "SIM_DataUtils.h"
13 #include "SIM_PhysicalParms.h"
14 #include <UT/UT_Matrix.h>
15 #include <UT/UT_Vector3.h>
16 #include <UT/UT_VectorTypes.h>
17 
19 class SIM_Geometry;
20 class SIM_Position;
21 class SIM_Motion;
22 class SIM_ForceResolver;
23 
24 /// This class is used for callbacks from SIM_Force::getPointForces().
26 {
27 public:
29  { }
31  { }
32 
33  /// This callback is called for each point in a geometry. This callback
34  /// is executed by SIM_Force::getPointForces(). The returned force
35  /// and torque are in either geometry space or world space depnding
36  /// on the value of the forcesinworldspace flag passed to the
37  /// getPointForces function.
38  virtual void forceCallbackOffset(GA_Offset ptoff,
39  const UT_Vector3 &force,
40  const UT_Vector3 &torque) = 0;
41 };
42 
43 /// This is the definition of the SIM_Force interface. The only function that
44 /// needs to be overridden (besides any standard SIM_Data overrides) is the
45 /// getForceSubclass() function.
46 class SIM_API SIM_Force : public SIM_Data
47 {
48 public:
49  typedef enum
50  {
53  SIM_FORCE_SAMPLESPHERE
54  } SIM_ForceSample;
55 
56  /// Returns the force and torque applied by this force to a point.
57  /// This function calls getForceSubclass().
58  void getForce(const SIM_Object &object,
59  const UT_Vector3 &position,
60  const UT_Vector3 &velocity,
61  const UT_Vector3 &angvel,
62  const fpreal mass,
64  UT_Vector3 &torque) const;
65  /// Returns the forces and torques applied by this force to a list
66  /// of points. This function calls getForceSetSubclass().
67  /// This function is available so that subclasses that implement
68  /// getForceSetSubclass can make use of multithreading for a
69  /// set of force calculations. Returns true if ok, false otherwise.
70  /// (We use this return value to determine whether or not a subclass
71  /// actually implements this function)
72  bool getForceSet(const SIM_Object &object,
73  const UT_Vector3Array &positions,
74  const UT_Vector3Array &velocities,
75  const UT_Vector3Array &angvelocities,
76  const UT_FloatArray &masses,
77  UT_Vector3Array &forces,
78  UT_Vector3Array &torques) const;
79  /// Creates a resolver to evaluate this force on the given object.
80  /// The caller must delete the returned resolver.
81  SIM_ForceResolver *getForceResolver(const SIM_Object &object) const;
82 
83  /// Returns the force and torque applied by this force to a circle.
84  /// This function calls getForceOnCircleSubclass().
85  void getForceOnCircle(const SIM_Object &object,
86  const UT_Vector3 &position,
87  const UT_Vector3 &normal,
88  const fpreal radius,
89  const UT_Vector3 &velocity,
90  const UT_Vector3 &angvel,
91  const fpreal mass,
93  UT_Vector3 &torque) const;
94  /// Returns the force and torque applied by this force to a sphere.
95  /// This function calls getForceOnSphereSubclass().
96  void getForceOnSphere(const SIM_Object &object,
97  const UT_Vector3 &position,
98  const fpreal radius,
99  const UT_Vector3 &velocity,
100  const UT_Vector3 &angvel,
101  const fpreal mass,
102  UT_Vector3 &force,
103  UT_Vector3 &torque) const;
104 
105  /// Returns the derivatives of force & torque with respect
106  /// to position and velocity. The jacobians are 6x6 matrices
107  /// which will be initialized as UT_Matrix(1, 6, 1, 6).
108  void getForceJacobian(const SIM_Object &object,
109  const UT_Vector3 &position,
110  const UT_Vector3 &velocity,
111  const UT_Vector3 &angvel,
112  const fpreal mass,
113  UT_Matrix &dFdX,
114  UT_Matrix &dFdV) const;
115 
116 
117  /// Allows solvers to query what the optimal sampling type
118  /// for this force would be. Solvers do not have to respect this.
119  /// This should be user overrideable so users can trade efficiency
120  /// for accuracy.
121  SIM_ForceSample getOptimalForceSampling() const;
122 
123  /// This is a convenience function for applying a force to each
124  /// point in a piece of geometry. For each point in the geometry,
125  /// the force on that point is calculated with the getForce()
126  /// function. The result of each call is passed to the
127  /// SIM_PointForceCallback::forceCallback() function, along with
128  /// the point number. The position, velocity, and mass for each
129  /// point come from the point attributes (if they exist), modified
130  /// by the SIM_Position or SIM_Motion data if they are passed in.
131  void getPointForces(SIM_PointForceCallback &cb,
132  const SIM_Object &object,
133  const GU_ConstDetailHandle &gdh,
134  const UT_DMatrix4 &geoxform,
135  const SIM_Position *position,
136  const SIM_Motion *motion,
137  bool forcesinworldspace) const;
138 
139 protected:
140  explicit SIM_Force(const SIM_DataFactory *factory);
141  ~SIM_Force() override;
142 
143  /// Looks for a SIM_Noise subdata and multiplies the force or torque
144  /// vector by the noise value at the specified position.
145  void applyNoise(const UT_Vector3 &pos,
146  UT_Vector3 &forceortorque) const;
147  /// Looks for a SIM_Noise subdata and multiplies the force and torque
148  /// vector by the noise value at the specified position. This is
149  /// equivalent to calling the alternate applyNoise function twice,
150  /// but eliminates the need to look up the noise value twice.
151  void applyNoise(const UT_Vector3 &pos,
152  UT_Vector3 &force,
153  UT_Vector3 &torque) const;
154  /// The dFdX and dFdV jacobians should already be filled out
155  /// with the jacobians of this force prior to noise. They are
156  /// then scaled to match the magnitude of the noise at this location.
157  void applyNoiseJacobian(const UT_Vector3 &pos,
158  UT_Matrix &dFdX,
159  UT_Matrix &dFdV) const;
160 
161  /// Returns the force and torque applied by this force to a point. The
162  /// outputs may be modified according to the information passed in about
163  /// the object to which the force is being applied. The default
164  /// implementation sets the force and torque to zero.
165  virtual void getForceSubclass(const SIM_Object &object,
166  const UT_Vector3 &position,
167  const UT_Vector3 &velocity,
168  const UT_Vector3 &angvel,
169  const fpreal mass,
170  UT_Vector3 &force,
171  UT_Vector3 &torque) const;
172  /// Creates a force resolver to evaluate this force in a threadsafe
173  /// manner.
174  virtual SIM_ForceResolver *getForceResolverSubclass(const SIM_Object &object) const;
175  /// Returns the forces and torques applied by this force to a list of
176  /// points. Returns true if ok, false otherwise. This return value
177  /// is used to determine whether or not subclasses actually implement
178  /// this function.
179  /// If this is implemented, it is the implementations responsibility
180  /// to resize the forces & torque arrays appropriately.
181  virtual bool getForceSetSubclass(const SIM_Object &object,
182  const UT_Vector3Array &positions,
183  const UT_Vector3Array &velocities,
184  const UT_Vector3Array &angvelocities,
185  const UT_FloatArray &masses,
186  UT_Vector3Array &forces,
187  UT_Vector3Array &torque) const;
188  /// Returns the force and torque applied by this force to a circle. The
189  /// outputs may be modified according to the information passed in about
190  /// the object to which the force is being applied. The default
191  /// implementation calls getForce() and assumes this is the force on
192  /// a unit area. So the force and torque are then scaled by the area
193  /// of the circle.
194  virtual void getForceOnCircleSubclass(const SIM_Object &object,
195  const UT_Vector3 &position,
196  const UT_Vector3 &normal,
197  const fpreal radius,
198  const UT_Vector3 &velocity,
199  const UT_Vector3 &angvel,
200  const fpreal mass,
201  UT_Vector3 &force,
202  UT_Vector3 &torque) const;
203  /// Returns the force and torque applied by this force to a sphere. The
204  /// outputs may be modified according to the information passed in about
205  /// the object to which the force is being applied. The default
206  /// implementation calls getForce() and assumes that the result
207  /// is a force per unit volume. The force and torque are then
208  /// scaled by the volume of the sphere.
209  virtual void getForceOnSphereSubclass(const SIM_Object &object,
210  const UT_Vector3 &position,
211  const fpreal radius,
212  const UT_Vector3 &velocity,
213  const UT_Vector3 &angvel,
214  const fpreal mass,
215  UT_Vector3 &force,
216  UT_Vector3 &torque) const;
217 
218  /// Returns the derivatives of force & torque with respect
219  /// to position and velocity. The jacobians are 6x6 matrices
220  /// indexed from 1 (ie, dFdX(1,1) is first element).
221  /// The default behaviour is to return 0 matrices. Note that
222  /// the matrices are already initialized to 0 when this is called.
223  virtual void getForceJacobianSubclass(const SIM_Object &object,
224  const UT_Vector3 &position,
225  const UT_Vector3 &velocity,
226  const UT_Vector3 &angvel,
227  const fpreal mass,
228  UT_Matrix &dFdX,
229  UT_Matrix &dFdV) const;
230 
231  /// Allows solvers to query what the optimal sampling type
232  /// for this force would be. Solvers do not have to respect this.
233  /// This should be user overrideable so users can trade efficiency
234  /// for accuracy.
235  virtual SIM_ForceSample getOptimalForceSamplingSubclass() const;
236 
237 private:
240 };
241 
242 /// This class is used to create a usually threadsafe resolver
243 /// to evaluate forces. It binds most of the data to cut the number
244 /// of parameter evaluations needed, caching where sensible.
245 /// Each thread should have its own resolver for thread-local caches,
246 /// so use the copy() method for each thread.
248 {
249 public:
251  SIM_ForceResolver(const SIM_Force *force, const SIM_Object *obj);
253  virtual ~SIM_ForceResolver();
254 
255  SIM_ForceResolver &operator=(const SIM_ForceResolver &src);
256 
257  virtual SIM_ForceResolver *copy() const = 0;
258 
259  /// Defaults to the resolver being threadsafe provided all
260  /// of the noise resolvers are threadsafe.
261  virtual bool threadsafe() const;
262 
263  virtual void getForce(const UT_Vector3 &position,
264  const UT_Vector3 &velocity,
265  const UT_Vector3 &angvel,
266  const fpreal mass,
267  UT_Vector3 &force,
268  UT_Vector3 &torque) = 0;
269 
270  /// Whether the getForceJacobian returns non-zero values.
271  /// The default implementation is to always return a 0 jacobian,
272  /// hence hasJacobian of false.
273  virtual bool hasJacobian() const { return false; }
274  virtual void getForceJacobian(const UT_Vector3 &position,
275  const UT_Vector3 &velocity,
276  const UT_Vector3 &angvel,
277  const fpreal mass,
278  UT_Matrix &dFdX,
279  UT_Matrix &dFdV);
280 
281  /// Does componentwise multiplication of the given vectors
282  /// with our noise resolvers.
283  void applyNoise(const UT_Vector3 &pos,
284  UT_Vector3 &forceortorque);
285  void applyNoise(const UT_Vector3 &pos,
286  UT_Vector3 &force,
287  UT_Vector3 &torque);
288  void applyNoiseJacobian(const UT_Vector3 &pos,
289  UT_Matrix &dFdX,
290  UT_Matrix &dFdV);
291 
292 protected:
294 };
295 
296 
298 {
299 public:
301  const SIM_Object *object)
302  {
303  myForce = force;
304  myObject = object;
305  }
306 
307  SIM_ForceResolver *copy() const override
308  {
309  return new SIM_ForceResolverGeneric(*this);
310  }
311 
312  bool threadsafe() const override { return false; }
313 
315  const UT_Vector3 &velocity,
316  const UT_Vector3 &angvel,
317  const fpreal mass,
318  UT_Vector3 &force,
319  UT_Vector3 &torque) override
320  {
321  myForce->getForce(*myObject, position, velocity, angvel,
322  mass, force, torque);
323  }
324  bool hasJacobian() const override { return true; }
326  const UT_Vector3 &velocity,
327  const UT_Vector3 &angvel,
328  const fpreal mass,
329  UT_Matrix &dFdX,
330  UT_Matrix &dFdV) override
331  {
332  myForce->getForceJacobian(*myObject,
333  position, velocity, angvel,
334  mass,
335  dFdX, dFdV);
336  }
337 protected:
340 };
341 
342 #endif
343 
#define DECLARE_STANDARD_GETCASTTOTYPE()
Definition: SIM_DataUtils.h:50
#define DECLARE_CLASSNAME(DataClass, SuperClass)
Definition: SIM_DataUtils.h:20
const SIM_Object * myObject
Definition: SIM_Force.h:339
bool threadsafe() const override
Definition: SIM_Force.h:312
SIM_ForceResolverGeneric(const SIM_Force *force, const SIM_Object *object)
Definition: SIM_Force.h:300
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
SIM_API const UT_StringHolder torque
virtual bool hasJacobian() const
Definition: SIM_Force.h:273
GA_Size GA_Offset
Definition: GA_Types.h:641
void getForce(const UT_Vector3 &position, const UT_Vector3 &velocity, const UT_Vector3 &angvel, const fpreal mass, UT_Vector3 &force, UT_Vector3 &torque) override
Definition: SIM_Force.h:314
bool hasJacobian() const override
Definition: SIM_Force.h:324
This is the default implementation for standard motion data.
Definition: SIM_Motion.h:18
void getForceJacobian(const UT_Vector3 &position, const UT_Vector3 &velocity, const UT_Vector3 &angvel, const fpreal mass, UT_Matrix &dFdX, UT_Matrix &dFdV) override
Definition: SIM_Force.h:325
GA_API const UT_StringHolder mass
SIM_API const UT_StringHolder force
fpreal64 fpreal
Definition: SYS_Types.h:277
virtual ~SIM_PointForceCallback()
Definition: SIM_Force.h:30
SIM_API const UT_StringHolder position
#define SIM_API
Definition: SIM_API.h:12
This class is used for callbacks from SIM_Force::getPointForces().
Definition: SIM_Force.h:25
const SIM_Force * myForce
Definition: SIM_Force.h:338
SIM_ForceResolver * copy() const override
Definition: SIM_Force.h:307
UT_ValArray< SIM_PropertyResolver * > myNoiseResolvers
Definition: SIM_Force.h:293
GLenum src
Definition: glcorearb.h:1793