HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_Turbulence.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: GU library (C++)
7  *
8  * COMMENTS: Turbulence functions
9  * This function never deletes the data gdp. Therefore, if
10  * the source changes, it's up to the caller to reset the data.
11  *
12  */
13 
14 #ifndef __GU_Turbulence_h__
15 #define __GU_Turbulence_h__
16 
17 #include "GU_API.h"
18 #include <UT/UT_Vector3.h>
19 #include <UT/UT_BitArray.h>
20 #include <GEO/GEO_Detail.h>
21 #include <GEO/GEO_PrimPart.h> // Only for GEO_ParticleVertexIndex
22 #include "GU_Attractor.h"
23 #include "GU_Detail.h"
24 
25 class GEO_PrimParticle;
26 class GU_RayIntersect;
27 
29 {
31  GU_RUNGEKUTTA_2, // 2nd order Runge-Kutta
32  GU_RUNGEKUTTA_4 // 4th order Runge-Kutta
33 };
34 
35 enum
36 {
40 };
41 
43 {
44 public:
46  euler = GU_EULER;
47  singleAttractor = 0;
48  modifySource = 0;
49  birthAll = 0;
50  destroyMode = 0;
51  accurateMove = 0;
52  jitterBirth = 0;
53  addId = 0;
54  splitting = 0;
55  contact = 0;
56  pointReuse = 0;
57  revertFixed = 1;
58  };
59 
60  unsigned singleAttractor:1,
61  modifySource:1, // Modify source (no particles)
62  birthAll:1, // If we're modifying source, start all
63  // at the first frame
64  destroyMode:1, // Destroy dead particles
65  accurateMove:1, // Accurate move mode
66  jitterBirth:1, // Jitter births across time step
67  addId:1, // Adds unique particle IDs
68  splitting:2, // 0 = no splitting
69  // 1 = split on contact
70  // 2 = split on death
71  contact:2, // 0 = particles die on contact
72  // 1 = particles bounce on contact
73  // 2 = particles stick on contact
74  pointReuse:2, // 0 = reuse points in a loop
75  // 1 = use first unused point
76  // 2 = don't reuse points
77  revertFixed:1; // Fixed points snap to source pos
78  GU_INTEGRATION_TYPE euler; // Integration type
79 };
80 
81 
83 {
84 public:
85  GU_Turbulence();
86  virtual ~GU_Turbulence();
87 
88 //
89 // The cook method will update the gdp to time "now"
90  void cook(float now, float time_step = 1./30.);
91 
92 //
93 // This method forces a reset of the system
94  void reset();
95 
96  void setGdp(GU_Detail *g) { myGdp = g;
97  initDetail(g);
98  }
99  void setSource(GU_Detail *gdp) { source = gdp;
100  initSource(source);
101  }
102  void setCollision(GU_Detail *gdp) { collision = gdp;
103  buildCollisionCache();
104  initCollision(collision);
105  }
106  void setStartTime(float t) { startTime = t; }
107  void setPreroll(float t) { preroll = t; }
108  void setLimits(const UT_Vector3 &neg, const UT_Vector3 &pos);
109  void setGain(float n, float t) { gainNml = n; gainTan = t; }
110 
111  void setModifySource(int onOff) { flags.modifySource = onOff; }
112  int getModifySource() const { return flags.modifySource; }
113  void setPointReuse(int val) { flags.pointReuse = val; }
114  int getPointReuse() const { return flags.pointReuse; }
115  void setBirthAll(int onOff) { flags.birthAll = onOff; }
116  int getBirthAll() const { return flags.birthAll; }
117  void setRevertFixed(int onOff) { flags.revertFixed = onOff; }
118  int getRevertFixed() const { return flags.revertFixed; }
119 //
120 // Euler integration is faster than Runge-Kutta (euler = 0), however,
121 // Runge-Kutta produces more realistic results (and is less likely
122 // to explode).
123  void setEuler(int onOff)
124  {
125  flags.euler = (onOff) ? GU_EULER : GU_RUNGEKUTTA_4;
126  }
128  {
129  flags.euler = t;
130  }
131  int getEuler() const { return flags.euler==GU_EULER;}
132  GU_INTEGRATION_TYPE getIntegration() const { return flags.euler; }
133 
134 //
135 // When dealing with particle systems, it's more efficient to leave
136 // dead particles in the system as potential new births, however,
137 // if the destroyMode is set, these particles are actually destroyed.
138 // This is important if the number of points must equal the number of
139 // particles.
140  void setDestroyMode(int onOff) { flags.destroyMode = onOff; }
141  int getDestroyMode() const { return flags.destroyMode; }
142 
143 //
144 // One problem is that if the source geometry is changing, as we cook
145 // over multiple frames, the source geometry doesn't change. If the
146 // accuracy mode is set, then we call the protected update methods
147 // to make sure the geometry is accurate for jumping frames.
148 // This is potentially very expensive if the jitterBirth option is
149 // set.
150  void setAccurateMove(int onOff) { flags.accurateMove = onOff; }
151  int getAccurateMove() const { return flags.accurateMove; }
152 
153 //
154 // Jittering the birth causes particles to be born at random times over the
155 // time step.
156  void setJitterBirth(int onOff) { flags.jitterBirth = onOff; }
157  int getJitterBirth() const { return flags.jitterBirth; }
158 
159 //
160 // Single attractor causes each particle to be acted upon by only one
161 // attractor.
162  void setSingleAttractor(int onOff)
163  { flags.singleAttractor = onOff; }
164  int getSingleAttractor() const
165  { return flags.singleAttractor; }
166 
167  void setAddId(int onOff) { flags.addId = onOff; }
168  int getAddId() const { return flags.addId; }
169 
170  void setSplitOff() { flags.splitting = 0; }
171  void setSplitContact() { flags.splitting = 1; }
172  void setSplitDeath() { flags.splitting = 2; }
173  int getSplitting() const { return flags.splitting; }
174 
175  void setDieOnContact() { flags.contact = 0; }
176  void setBounceOnContact() { flags.contact = 1; }
177  void setStickOnContact() { flags.contact = 2; }
178  int getContact() { return flags.contact; }
179 
180  void setFixedPoints(const GA_PointGroup *group);
181  void setInputGroup(const GA_PointGroup *group);
182 
184  { attractor.setAttractor(gdp); initAttractor(gdp); }
185 
186 //
187 //
189  { attractor.initPointAttractorForce(); }
190 
192  { attractor.cleanPointAttractorForce(); }
193 
194 //
195 // Get the force on a point/particle - feel free to call "getAttractorForce"
196 // from within getForce()
198  { attractor.getAttractorForce(myGdp->getPos3(ptoff), force,
199  getSingleAttractor(), myGdp->pointIndex(ptoff)); }
200 //
201 // In case the sub-class needs to know anything about the attractor
202  virtual void initAttractor (GU_Detail* ) {};
203 
204 //
205 // Calling this method will force a re-find of the system next cook
206  void zeroSystem() { system = 0; }
207  GEO_PrimParticle *getParticles() { return system; }
208 
209  const GA_PointGroup *getFixedPoints() { return fixedPoints; }
210 
211 protected:
212 //
213 // The following virtual methods are used to define the behaviour of the
214 // system. They are intended to be sub-classed by the user of this
215 // class.
216 
217 //
218 // The following method is can be used to pre-evaluate stuff. It is
219 // called every time the time changes.
220  virtual int changeTime(float t);
221 //
222 // When birthing particles, we need to know how long lived they are
223  virtual float getBirthRate(float t);
224 //
225 // Get the life time for a particle. Split will be 1 if the particle
226 // is a split particle, 0 otherwise
227  virtual float getLifetime(float t, int split);
228 //
229 // Number of particles to split into (on contact or death)
230  virtual int getNumSplit(float t);
231 
232 //
233 // Set the birth attributes for a particle. This routine is responsible
234 // for setting all attributes except for id and lifetime. It is
235 // very important to set the velocity (by default, it will be 0)
236 // If the birth particle is a split particle, then the source particle
237 // is the point passed, otherwise, it's the point from the source which
238 // is passed.
239  virtual void setBirthAttributes(GA_Offset ptoff,
240  GA_Offset srcptoff,
241  bool split) = 0;
242 
243 //
244 // Get the mass of a point
245  virtual float getMass(float t, GA_Offset ptoff) = 0;
246 
247  virtual void getForce(float t, GA_Offset ptoff,
248  UT_Vector3 &force) = 0;
249 
250 //
251 // These methods are possibly called when the accurateMove flag is set
252  virtual void updateSource(float t);
253  virtual void updateCollision(float t);
254  virtual void updateAttractor(float t);
255 
256 //
257 // Initialize all the attributes for a GU_Detail - the base class method
258 // should always be called (if subclassed)
259  virtual void initDetail(GU_Detail *gdp);
260 
261 //
262 // In case the sub-class needs to know anything about the source
263  virtual void initSource(GU_Detail *src);
264 
265 //
266 // In case the sub-class needs to do anything whenever a reset is done.
267  virtual void resetSource(GU_Detail *src);
268 
269 //
270 // In case the sub-class needs to know anything about the collision object
271  virtual void initCollision(GU_Detail *coll);
272 
273 // WARNING, calling this method may force a particle system to be added
274  GEO_PrimParticle *getSystem();
275 
276 // Just in case someone needs to be able to get at these...
277  GU_Detail *getMySource() { return source; }
278  GU_Detail *getMyGdp() { return myGdp; }
279 
280 protected:
281 // Here is the protected data
282 // First, the attribute offsets which must exist for particle systems
283  GA_RWHandleV3 myVelocityHandle; // Handle of velocity attribute
284  GA_RWHandleV2 myLifeHandle; // Handle of time alive
286  GA_RWHandleI myPStateHandle; // Handle of the particle
287  // state attribute
288 
289  UT_Vector3 negLimit; // Limit planes
291  float gainNml, gainTan;
292 
293  UT_BitArray deadPoints; // A bit array for modifying source
294  UT_BitArray stuckPoints; // A bit array of all stuck points
296 
297 private:
298  void cookTime(float t, float tinc);
299  void updateBitFields();
300  void changeVelocity(float t, float tinc, GA_Offset ptoff);
301  void splitParticle(float t, GA_Offset vtxoff,
302  GEO_PrimParticle *part);
303  void killParticle(float t, GEO_ParticleVertexIndex vtxidx,
304  GA_Offset vtxoff, GEO_PrimParticle *part);
305  void birthParticle(GEO_PrimParticle *, float t, float tinc,
306  GA_Offset splitpt = GA_INVALID_OFFSET);
307  void killPoint(GA_Offset ptoff);
308  int birthPoint(float t, float tinc);
309  int movePoint(GU_Detail *gdp, GA_Offset ptoff, float tinc);
310 
311  // This method is called every time the collision gdp is set
312  void buildCollisionCache();
313 
314 
315  GU_Detail *myGdp;
316  GU_Detail *source;
317  GU_Detail *collision;
318  GU_RayIntersect *rayIntersector; // Collision object intersector
319  GU_Attractor attractor;
320 
321  GEO_PrimParticle *system;
322 
323  const GA_PointGroup *inputGroup; // only give birth from the points here
324 
326 
327  float lastCookTime;
328  float startTime;
329  float preroll;
330 
331  int idCount; // For unique IDs
332  GA_Iterator mySourcePoint; // Source point to use for birthing
333  float nborn; // Residue of particles to birth
334  unsigned mySeed;
335 };
336 
337 #endif
UT_BitArray deadPoints
GLbitfield flags
Definition: glcorearb.h:1596
void setSplitContact()
Iteration over a range of elements.
Definition: GA_Iterator.h:29
int getBirthAll() const
void setCollision(GU_Detail *gdp)
UT_Vector3 negLimit
void setSource(GU_Detail *gdp)
Definition: GU_Turbulence.h:99
GLboolean GLboolean g
Definition: glcorearb.h:1222
void setBirthAll(int onOff)
void cleanupAttractor()
UT_BitArray stuckPoints
void setAccurateMove(int onOff)
void setAttractor(GU_Detail *gdp)
void setStartTime(float t)
void setDieOnContact()
#define GA_INVALID_OFFSET
Definition: GA_Types.h:678
void setBounceOnContact()
void initAttractor()
int getDestroyMode() const
GA_Size GA_Offset
Definition: GA_Types.h:641
GU_Detail * getMySource()
GU_Detail * getMyGdp()
int getModifySource() const
void setEuler(int onOff)
GLdouble n
Definition: glcorearb.h:2008
void setPreroll(float t)
GLboolean reset
Definition: glad.h:5138
void setModifySource(int onOff)
int getSplitting() const
int getJitterBirth() const
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
GU_INTEGRATION_TYPE
Definition: GU_Turbulence.h:28
int getAddId() const
void setGain(float n, float t)
#define GU_API
Definition: GU_API.h:14
void setSingleAttractor(int onOff)
int getSingleAttractor() const
GA_RWHandleV3 myVelocityHandle
GA_RWHandleV2 myLifeHandle
const GA_PointGroup * getFixedPoints()
GU_INTEGRATION_TYPE getIntegration() const
void setDestroyMode(int onOff)
int getRevertFixed() const
GLdouble t
Definition: glad.h:2397
int getAccurateMove() const
void setAddId(int onOff)
void setPointReuse(int val)
SIM_API const UT_StringHolder force
GA_RWHandleI myIDHandle
int getPointReuse() const
GA_Size GEO_ParticleVertexIndex
Definition: GEO_PrimPart.h:25
void setSplitDeath()
GA_RWHandleI myPStateHandle
GEO_PrimParticle * getParticles()
void setSplitOff()
UT_Vector3 posLimit
GLuint GLfloat * val
Definition: glcorearb.h:1608
void setGdp(GU_Detail *g)
Definition: GU_Turbulence.h:96
void setIntegration(GU_INTEGRATION_TYPE t)
void setJitterBirth(int onOff)
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
virtual void initAttractor(GU_Detail *)
void getAttractorForce(GA_Offset ptoff, UT_Vector3 &force)
void setRevertFixed(int onOff)
GU_INTEGRATION_TYPE euler
Definition: GU_Turbulence.h:78
int getEuler() const
const GA_PointGroup * fixedPoints
GLenum src
Definition: glcorearb.h:1793
void setStickOnContact()