HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SOP_BouncyAgent.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  */
27 
28 /*! @file SOP_BouncyAgent.C
29 
30  @brief Demonstrates example for creating a procedural agent primitive.
31 
32  The node creates an agent primitive for every point from its input geometry
33  that uses the same shared agent definition. The agent definition itself is a
34  unit polygonal sphere that has skin weights bound to two joints (a parent and
35  a child) with animation that bounces it in TY.
36 
37 */
38 
39 #include "SOP_BouncyAgent.h"
40 
41 #include <OP/OP_AutoLockInputs.h>
42 #include <OP/OP_Operator.h>
43 #include <OP/OP_OperatorTable.h>
44 #include <PRM/PRM_Include.h>
45 #include <PRM/PRM_Type.h>
46 #include <CH/CH_Manager.h>
47 #include <GU/GU_Agent.h>
48 #include <GU/GU_AgentRig.h>
49 #include <GU/GU_AgentShapeLib.h>
50 #include <GU/GU_AgentLayer.h>
51 #include <GU/GU_PrimPacked.h>
52 #include <GU/GU_PrimSphere.h>
55 #include <GA/GA_AIFIndexPair.h>
56 #include <CL/CL_Clip.h>
57 #include <CL/CL_Track.h>
58 #include <UT/UT_Array.h>
59 #include <UT/UT_DSOVersion.h>
60 #include <UT/UT_Interrupt.h>
61 #include <UT/UT_String.h>
62 #include <UT/UT_StringArray.h>
63 #include <UT/UT_WorkBuffer.h>
64 #include <stdlib.h>
65 
66 using namespace HDK_Sample;
67 
68 // Provide entry point for installing this SOP.
69 void
71 {
72  OP_Operator *op = new OP_Operator(
73  "hdk_bouncyagent",
74  "BouncyAgent",
77  1, // min inputs
78  1 // max inputs
79  );
80  table->addOperator(op);
81 }
82 
83 OP_Node *
85  OP_Network *net, const char *name, OP_Operator *op)
86 {
87  return new SOP_BouncyAgent(net, name, op);
88 }
89 
90 // SOP Parameters.
91 static PRM_Name sopAgentName("agentname", "Agent Name");
92 static PRM_Default sopAgentNameDef(0, "agent1");
93 static PRM_Name sopHeight("height", "Height");
94 static PRM_Default sopHeightDef(5.0);
95 static PRM_Name sopClipLength("cliplength", "Clip Length"); // seconds
96 static PRM_Name sopClipOffset("clipoffset", "Clip Offset"); // seconds
97 static PRM_Default sopClipOffsetDef(0, "$T");
98 static PRM_Range sopClipOffsetRange(PRM_RANGE_UI, 0, PRM_RANGE_UI, 10);
99 static PRM_Name sopReload("reload", "Reload");
100 
103 {
104  PRM_Template(PRM_ALPHASTRING, 1, &sopAgentName, &sopAgentNameDef),
105  PRM_Template(PRM_FLT_J, 1, &sopHeight, &sopHeightDef),
106  PRM_Template(PRM_FLT_J, 1, &sopClipLength, PRMoneDefaults,
107  0, &PRMrulerRange),
108  PRM_Template(PRM_FLT_J, 1, &sopClipOffset, &sopClipOffsetDef,
109  0, &sopClipOffsetRange),
110  PRM_Template(PRM_CALLBACK, 1, &sopReload, 0, 0, 0,
111  &SOP_BouncyAgent::onReload),
112  PRM_Template() // sentinel
113 };
114 
115 // Constructor
117  OP_Network *net, const char *name, OP_Operator *op)
118  : SOP_Node(net, name, op)
119 {
120  // This indicates that this SOP manually manages its data IDs,
121  // so that Houdini can identify what attributes may have changed,
122  // e.g. to reduce work for the viewport, or other SOPs that
123  // check whether data IDs have changed.
124  // By default, (i.e. if this line weren't here), all data IDs
125  // would be bumped after the SOP cook, to indicate that
126  // everything might have changed.
127  // If some data IDs don't get bumped properly, the viewport
128  // may not update, or SOPs that check data IDs
129  // may not cook correctly, so be *very* careful!
131 }
132 
133 // Destructor
135 {
136 }
137 
138 enum
139 {
143  // Set up exclusive rig index range for joints
146 };
147 
148 // Create the rig.
149 // Rigs define the names of the transforms in a tree hierarchy.
150 static GU_AgentRigPtr
151 sopCreateRig(const char *path)
152 {
153  UT_String rig_name = path;
154  rig_name += "?rig";
155  GU_AgentRigPtr rig = GU_AgentRig::addRig(rig_name);
156 
158  transforms.append("skin"); // SOP_SKIN_RIG_INDEX
159  transforms.append("parent"); // SOP_PARENT_RIG_INDEX
160  transforms.append("child"); // SOP_CHILD_RIG_INDEX
161 
162  UT_IntArray child_counts;
163  child_counts.append(0); // 'skin' has 0 children
164  child_counts.append(1); // 'parent' has 1 child
165  child_counts.append(0); // 'child' has 0 children
166 
167  UT_IntArray children;
168  // 'skin' has no children so we don't need to append anything for it
169  children.append(SOP_CHILD_RIG_INDEX); // 'parent' has 'child' as the child
170  // 'child' has no children so we don't need to append anything for it
171 
172  // now construct the rig
173  if (!rig->construct(transforms, child_counts, children))
174  return nullptr;
175  return rig;
176 }
177 
178 static GU_Detail *
179 sopCreateSphere(bool for_default)
180 {
181  GU_Detail *shape = new GU_Detail;
182  GU_PrimSphereParms sphere(shape);
183  if (for_default)
184  {
185  sphere.freq = 2;
186  sphere.type = GEO_PATCH_TRIANGLE;
188  }
189  else
190  {
191  // Position and scale the collision sphere to account for the
192  // deformation animation.
193  sphere.xform.scale(1.5, 1, 1.5);
194  sphere.xform.translate(0, 1, 0.5);
196  }
197  return shape;
198 }
199 
200 // For simplicity, we bind all points to all the transforms except for
201 // SOP_SKIN_RIG_INDEX.
202 static void
203 sopAddSkinWeights(const GU_AgentRig &rig, const GU_DetailHandle &shape)
204 {
205  GU_DetailHandleAutoWriteLock gdl(shape);
206  GU_Detail *gdp = gdl.getGdp();
207 
208  // Create skinning attribute with 2 regions and each point is bound to both
209  // rig transforms.
210  int num_regions = (SOP_JOINT_END - SOP_JOINT_BEGIN);
211  GEO_Detail::geo_NPairs num_pairs_per_pt(num_regions);
212  GA_RWAttributeRef capt = gdp->addPointCaptureAttribute(num_pairs_per_pt);
213  int regions_i = -1;
214  GA_AIFIndexPairObjects *regions
216  capt, regions_i);
217  regions->setObjectCount(num_regions);
218 
219  // Tell the skinning attribute the names of the rig transforms. This needs
220  // to be done after calling regions->setObjectCount().
221  GEO_RWAttributeCapturePath paths(gdp);
222  for (int i = 0; i < num_regions; ++i)
223  paths.setPath(i, rig.transformName(SOP_JOINT_BEGIN + i));
224 
225  // Set up the rest transforms for the skin weight bindings. For efficiency,
226  // these are actually stored in the skin weight bindings as the INVERSE of
227  // the world space rest transform of the joint.
228  for (int i = 0; i < num_regions; ++i)
229  {
231  // Recall that the unit sphere is created at the origin. So to position
232  // the parent joint at the base of the sphere, it should be a position
233  // (0, -1, 0). However, since these are actually inverses, we'll
234  // translate by the opposite sign instead.
235  if (i == 0)
236  r.myXform.translate(0, +1.0, 0);
237  else
238  r.myXform.translate(0, -1.0, 0);
239  regions->setObjectValues(i, regions_i, r.floatPtr(),
241  }
242 
243  // Set up the weights
244  const GA_AIFIndexPair *weights = capt->getAIFIndexPair();
245  weights->setEntries(capt, num_regions);
246  for (GA_Offset ptoff : gdp->getPointRange())
247  {
248  for (int i = 0; i < num_regions; ++i)
249  {
250  // Set the region index that the point is captured by.
251  // Note that these index into 'paths' above.
252  weights->setIndex(capt, ptoff, /*entry*/i, /*region*/i);
253  // Set the weight that the point is captured by transform i.
254  // Notice that all weights for the point should sum to 1.
255  fpreal weight = 1.0/num_regions;
256  weights->setData(capt, ptoff, /*entry*/i, weight);
257  }
258  }
259 }
260 
261 // Default convention is to prefix the shape name by the layer name
262 #define SOP_DEFAULT_SKIN_NAME GU_AGENT_LAYER_DEFAULT".skin"
263 #define SOP_COLLISION_SKIN_NAME GU_AGENT_LAYER_COLLISION".skin"
264 
265 // Create the shape library which contains a list of all the shape geometries
266 // that can be attached to the rig transforms.
267 static GU_AgentShapeLibPtr
268 sopCreateShapeLib(const char *path, const GU_AgentRig &rig)
269 {
270  UT_String shapelib_name = path;
271  shapelib_name += "?shapelib";
272  GU_AgentShapeLibPtr shapelib = GU_AgentShapeLib::addLibrary(shapelib_name);
273 
274  GU_DetailHandle skin_geo;
275  skin_geo.allocateAndSet(sopCreateSphere(true), /*own*/true);
276  sopAddSkinWeights(rig, skin_geo);
277  shapelib->addShape(SOP_DEFAULT_SKIN_NAME, skin_geo);
278 
279  // The collision geometry is intended to be simplified versions of the
280  // default layer shapes. The bounding box for the default layer shape is
281  // computed from the corresponding collision layer shape.
282  GU_DetailHandle coll_geo;
283  coll_geo.allocateAndSet(sopCreateSphere(false), /*own*/true);
284  shapelib->addShape(SOP_COLLISION_SKIN_NAME, coll_geo);
285 
286  return shapelib;
287 }
288 
289 // Create a default layer with the sphere as the geometry bound to the rig.
290 // Layers assign geometry from the shapelib to be used for the rig
291 // transforms.
292 // Agents must have at least 2 layers:
293 // GU_AGENT_LAYER_DEFAULT ("default"
294 // - Used for display/render
295 // GU_AGENT_LAYER_COLLISION ("collision")
296 // - Simple geometry to be used for the bounding box that
297 // encompasses the corresponding shape in default layer for all
298 // possible local deformations.
299 // In general, it can have more layers and we can set which of those we use
300 // for the default and collision.
301 static GU_AgentLayerPtr
302 sopCreateDefaultLayer(
303  const char *path,
304  const GU_AgentRigPtr &rig,
305  const GU_AgentShapeLibPtr &shapelib)
306 {
307  UT_StringArray shape_names;
308  UT_IntArray transform_indices;
309  UT_Array<bool> deforming;
310 
311  // Simply bind the skin geometry to the 'skin' transform which we know is
312  // transform index 0.
313  shape_names.append(SOP_DEFAULT_SKIN_NAME);
314  transform_indices.append(SOP_SKIN_RIG_INDEX);
315  deforming.append(true); // has skin weights
316 
317  UT_String unique_name = path;;
318  unique_name += "?default_layer";
320  = GU_AgentLayer::addLayer(unique_name, rig, shapelib);
321  if (!layer->construct(shape_names, transform_indices, deforming))
322  return nullptr;
323 
325  layer->setName(layer_name);
326 
327  return layer;
328 }
329 
330 // See also comments for sopCreateDefaultLayer().
331 static GU_AgentLayerPtr
332 sopCreateCollisionLayer(
333  const char *path,
334  const GU_AgentRigPtr &rig,
335  const GU_AgentShapeLibPtr &shapelib)
336 {
337  UT_StringArray shape_names;
338  UT_IntArray transform_indices;
339  UT_Array<bool> deforming;
340 
341  // For character rigs, the collision shapes are typically attached to the
342  // joint transforms so that they can proxy for skin deformation.
343  shape_names.append(SOP_COLLISION_SKIN_NAME);
344  transform_indices.append(SOP_PARENT_RIG_INDEX);
345  deforming.append(false); // has NO skin weights
346 
347  UT_String unique_name = path;;
348  unique_name += "?collision_layer";
350  layer = GU_AgentLayer::addLayer(unique_name, rig, shapelib);
351  if (!layer->construct(shape_names, transform_indices, deforming))
352  return nullptr;
353 
355  layer->setName(layer_name);
356 
357  return layer;
358 }
359 
360 static fpreal*
361 sopAddTrack(CL_Clip &chans, const GU_AgentRig &rig, int i, const char *trs_name)
362 {
363  UT_WorkBuffer str;
364  str.sprintf("%s:%s", rig.transformName(i).buffer(), trs_name);
365  return chans.addTrack(str.buffer())->getData();
366 }
367 
368 // Create some bouncy animation for the agent
369 static GU_AgentClipPtr
370 sopCreateBounceClip(CL_Clip& chans, const GU_AgentRigPtr &rig, fpreal height)
371 {
372  int num_samples = chans.getTrackLength();
373 
374  // Set the ty of the 'parent' transform that bounces. Note that these
375  // transforms here are in local space. The valid channel names are:
376  // Translate: tx ty tz
377  // Rotate: rx ry rz (euler angles in degrees, XYZ rotation order)
378  // Scale: sx sy sz
379  fpreal *ty = sopAddTrack(chans, *rig, SOP_PARENT_RIG_INDEX, "ty");
380  fpreal *sy = sopAddTrack(chans, *rig, SOP_PARENT_RIG_INDEX, "sy");
381  for (int i = 0; i < num_samples; ++i)
382  {
383  ty[i] = height * sin(i * M_PI / (num_samples-1));
384  // add some squash and stretch
385  sy[i] = 1.0 - SYSabs(0.5 * sin(i * M_PI / (num_samples-1)));
386  }
387 
388  // Set the ty of the 'child' transform. Note that these transforms here are
389  // in local space.
390  fpreal *tz = sopAddTrack(chans, *rig, SOP_CHILD_RIG_INDEX, "tz");
391  ty = sopAddTrack(chans, *rig, SOP_CHILD_RIG_INDEX, "ty");
392  for (int i = 0; i < num_samples; ++i)
393  {
394  ty[i] = 2.0; // sphere diameter
395  tz[i] = 1.5 * sin(i * M_PI / (num_samples-1)); // sway a bit forwards
396  }
397 
398  // Finally load the agent clip from the CL_Clip animation we created
399  GU_AgentClipPtr clip = GU_AgentClip::addClip("bounce", rig);
400  if (!clip)
401  return nullptr;
402  clip->load(chans);
403 
404  return clip;
405 }
406 
407 // Enable this to debug our definition
408 #define SOP_SAVE_AGENT_DEFINITION 0
409 
410 // Create the agent definition
412 SOP_BouncyAgent::createDefinition(fpreal t) const
413 {
414  // Typically, the definition is loaded from disk which has a filename for
415  // each of the different parts. Since we're doing this procedurally, we're
416  // going to just make up some arbitrary unique names using our node path.
417  UT_String path;
418  getFullPath(path);
419 
420  GU_AgentRigPtr rig = sopCreateRig(path);
421  if (!rig)
422  return nullptr;
423 
424  GU_AgentShapeLibPtr shapelib = sopCreateShapeLib(path, *rig);
425  if (!shapelib)
426  return nullptr;
427 
428  GU_AgentLayerPtr default_layer = sopCreateDefaultLayer(path,
429  rig, shapelib);
430  if (!default_layer)
431  return nullptr;
432 
433  GU_AgentLayerPtr collision_layer = sopCreateCollisionLayer(path,
434  rig, shapelib);
435  if (!collision_layer)
436  return nullptr;
437 
438  CL_Clip chans(CHgetManager()->getSample(CLIPLENGTH(t)));
439  chans.setSampleRate(CHgetManager()->getSamplesPerSec());
440  GU_AgentClipPtr clip = sopCreateBounceClip(chans, rig, HEIGHT(t));
441  if (!clip)
442  return nullptr;
443 
444 #if SOP_SAVE_AGENT_DEFINITION
445  // Once we have the definition, we can save out the files for loading with
446  // the Agent SOP as well. Or, we can examine them for debugging purposes.
447  {
448  UT_AutoJSONWriter writer("bouncy_rig.rig", /*binary*/false);
449  rig->save(writer);
450  }
451  {
452  UT_AutoJSONWriter writer("bouncy_shapelib.bgeo", /*binary*/true);
453  shapelib->save(writer);
454  }
455  {
456  UT_AutoJSONWriter writer("bouncy_layer.default.lay", /*binary*/false);
457  default_layer->save(writer);
458  }
459  {
460  UT_AutoJSONWriter writer("bouncy_layer.collision.lay", /*binary*/false);
461  collision_layer->save(writer);
462  }
463  {
464  chans.save("bouncy_bounce.bclip");
465  }
466 #endif
467 
468  // The agent definition is used to create agent primitives. Many agent
469  // primitives can share the same definition.
470  GU_AgentDefinitionPtr def(new GU_AgentDefinition(rig, shapelib));
471  if (!def)
472  return nullptr;
473  // The definition has a number of layers that be can assigned
474  def->addLayer(default_layer);
475  def->addLayer(collision_layer);
476  // ... and a number of clips that can be assigned to specific agent prims
477  def->addClip(clip);
478 
479  return def;
480 }
481 
482 /*static*/ int
483 SOP_BouncyAgent::onReload(
484  void *data, int index, fpreal t, const PRM_Template *tplate)
485 {
486  SOP_BouncyAgent* sop = static_cast<SOP_BouncyAgent*>(data);
487  if (!sop->getHardLock()) // only allow reloading if we're not locked
488  {
489  sop->myDefinition.reset();
490  sop->forceRecook();
491  }
492  return 1;
493 }
494 
495 // Compute the output geometry for the SOP.
496 OP_ERROR
498 {
499  fpreal t = context.getTime();
500 
501  // We must lock our inputs before we try to access their geometry.
502  // OP_AutoLockInputs will automatically unlock our inputs when we return.
503  // NOTE: Don't call unlockInputs yourself when using this!
504  OP_AutoLockInputs inputs(this);
505  if (inputs.lock(context) >= UT_ERROR_ABORT)
506  return error();
507 
508  // Duplicate the input geometry, but only if it was changed
509  int input_changed;
510  duplicateChangedSource(/*input*/0, context, &input_changed);
511 
512  // Detect if we need to rebuild the agent definition. For simplicity, we'll
513  // rebuild if any of our agent parameters changed. Note the use of the
514  // bitwise or operator to ensure that isParmDirty() is always called for
515  // all parameters.
516  bool agent_changed = isParmDirty(sopAgentName.getToken(), t);
517  agent_changed = isParmDirty(sopHeight.getToken(), t);
518  agent_changed |= isParmDirty(sopClipLength.getToken(), t);
519 
520  if (!myDefinition)
521  {
522  agent_changed = true;
523  input_changed = true;
524  }
525 
526  if (agent_changed)
527  {
528  myDefinition = createDefinition(t);
529  if (!myDefinition)
530  {
531  addError(SOP_MESSAGE, "Failed to create definition");
532  return error();
533  }
534  }
535 
536  if (input_changed)
537  {
538  // Delete all the primitives, keeping only the points
540 
541  // These UT_StringHolder objects make the hash table look ups more
542  // efficient.
543  UT_StringHolder default_layer(
545  UT_StringHolder collision_layer(
547 
548  // Create the agent primitives
549  myPrims.clear();
550  for (GA_Offset ptoff : gdp->getPointRange())
551  {
552  myPrims.append(GU_Agent::agent(*gdp, default_layer,
553  collision_layer, ptoff));
554  }
555 
556  // Bumping these 2 attribute owners is what we need to do when adding
557  // pack agent prims because it has a single vertex.
560  gdp->getPrimitiveList().bumpDataId(); // modified primitives
561  }
562 
563  if (agent_changed || input_changed)
564  {
565  // Create a name attribute for the agents
567  "name", 1));
568 
569  // Set the agent definition to the agent prims
571  UT_String agent_name;
572  AGENTNAME(agent_name, t);
573  int name_i = 0;
574  for (GU_PrimPacked *pack : myPrims)
575  {
576  GU_Agent* agent = UTverify_cast<GU_Agent*>(pack->implementation());
577  agent->setDefinition(pack, myDefinition);
578 
579  // We only have 1 clip that can be used in the definition here.
580  UT_StringArray clips;
581  clips.append(myDefinition->clip(0).name());
582  agent->setClipsByNames(pack, clips);
583 
584  // Convention for the agent primitive names is agentname_0,
585  // agentname_1, agentname_2, etc.
586  name.sprintf("%s_%d", agent_name.buffer(), name_i);
587  name_attrib.set(pack->getMapOffset(), name.buffer());
588  ++name_i;
589  }
590 
591  // Mark what modified
592  gdp->getPrimitiveList().bumpDataId();
593  name_attrib.bumpDataId();
594  }
595 
596  // Set the clip information for the agents. In general, agents can be set
597  // to evaluate an blended array of clips to evaluated at a specific clip
598  // offset.
599  for (GU_PrimPacked *pack : myPrims)
600  {
601  GU_Agent* agent = UTverify_cast<GU_Agent*>(pack->implementation());
602  agent->setClipTime(pack, /*clip index*/0, CLIPOFFSET(t));
603  }
604  gdp->getPrimitiveList().bumpDataId(); // we modified primitives
605 
606  return error();
607 }
608 
609 // Provide input labels.
610 const char *
611 SOP_BouncyAgent::inputLabel(unsigned /*input_index*/) const
612 {
613  return "Points to attach agents";
614 }
615 
const GA_AIFIndexPair * getAIFIndexPair() const
PRM_API const PRM_Type PRM_CALLBACK
static GU_AgentClipPtr addClip(const char *name, const GU_AgentRigConstPtr &rig)
Create an empty clip.
Generic Attribute Interface class to get/set data as index pairs.
virtual OP_ERROR error()
png_infop int transforms
Definition: png.h:2591
GLenum GLuint GLint GLint layer
Definition: glcorearb.h:1298
virtual bool setIndex(GA_Attribute *attrib, GA_Offset ai, int entry, int32 index) const =0
OP_ERROR lock(OP_Context &context)
Locks all inputs.
#define SOP_COLLISION_SKIN_NAME
fpreal getTime() const
Definition: OP_Context.h:34
GLsizei const GLchar *const * path
Definition: glcorearb.h:3340
void setClipsByNames(GU_PrimPacked *prim, const UT_StringArray &clip_names)
const UT_StringHolder & transformName(exint i) const
Return the name of the given transform.
Definition: GU_AgentRig.h:94
virtual void forceRecook(bool evensmartcache=true)
CL_Track * addTrack(const char *name)
#define SYSabs(a)
Definition: SYS_Math.h:1367
UT_ErrorSeverity
Definition: UT_Error.h:25
#define SOP_DEFAULT_SKIN_NAME
int save(UT_OStream &os, const CL_ClipPrivateIO *priv=0) const
void setDefinition(GU_PrimPacked *prim, const GU_AgentDefinitionPtr &definition)
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
Convenience class to store a bone capture region.
Read-Write string handle.
Definition: GA_Handle.h:942
void addError(int code, const char *msg=0)
Definition: SOP_Node.h:1145
png_uint_32 i
Definition: png.h:2877
#define M_PI
Definition: ImathPlatform.h:51
static GU_PrimPacked * agent(GU_Detail &dest, const StringType &default_layer=UTmakeUnsafeRef(GU_AGENT_LAYER_DEFAULT), const StringType &collision_layer=UTmakeUnsafeRef(GU_AGENT_LAYER_COLLISION), GA_Offset ptoff=GA_INVALID_OFFSET)
Convenience method to create a packed agent primitive.
GA_Size destroyPrimitives(const GA_Range &it, bool and_points=false)
Definition: GA_Detail.h:603
int getHardLock() const
Definition: OP_Node.h:1169
static GEO_Primitive * build(const GU_PrimSphereParms &parms, GA_PrimitiveTypeId type=GEO_PRIMSPHERE)
void allocateAndSet(GU_Detail *gdp, bool own=true)
GA_Size GA_Offset
Definition: GA_Types.h:617
const char * buffer() const
Definition: UT_String.h:503
This class provides a way to manage a reference to an attribute permitting Read-Write access...
A rig for the agent primitive.
Definition: GU_AgentRig.h:34
static OP_Node * myConstructor(OP_Network *, const char *, OP_Operator *)
GA_Range getPointRange(const GA_PointGroup *group=0) const
Get a range of all points in the detail.
Definition: GA_Detail.h:1616
static GU_AgentRigPtr addRig(const char *name)
CH_Manager * CHgetManager()
Definition: CH_Manager.h:1594
OP_ERROR duplicateChangedSource(unsigned idx, OP_Context &ctx, int *changed=0, bool force=false)
Only duplicates the source if the source has changed since the last call to this method.
SYS_FORCE_INLINE const char * buffer() const
void bumpDataId()
Use this to mark primitives or their intrinsic data as dirty.
SYS_FORCE_INLINE const UT_StringHolder & UTmakeUnsafeRef(const UT_StringRef &ref)
Convert a UT_StringRef into a UT_StringHolder that is a shallow reference.
void newSopOperator(OP_OperatorTable *table)
GA_AttributeSet & getAttributes()
Definition: GA_Detail.h:719
int getTrackLength(void) const
Definition: CL_Clip.h:82
Wrapper around hboost::intrusive_ptr.
SOP_NodeFlags mySopFlags
Definition: SOP_Node.h:1601
virtual void setObjectValues(int objid, int propid, const fpreal32 *v, int tuple_size)=0
virtual bool setData(GA_Attribute *attrib, GA_Offset ai, int entry, fpreal32 data, int data_component=0) const =0
static GA_AIFIndexPairObjects * getBoneCaptureRegionObjects(const GA_RWAttributeRef &h, int &property_i)
UT_StringHolder getFullPath() const
Definition: PRM_ParmOwner.h:59
#define GU_AGENT_LAYER_COLLISION
Definition: GU_Agent.h:32
GLboolean * data
Definition: glcorearb.h:130
GLuint const GLchar * name
Definition: glcorearb.h:785
SYS_FORCE_INLINE TO_T UTverify_cast(FROM_T from)
Definition: UT_Assert.h:175
PRM_API const PRM_Type PRM_FLT_J
void setManagesDataIDs(bool onOff)
Definition: SOP_NodeFlags.h:34
PRM_API PRM_Range PRMrulerRange
PRM_API const PRM_Type PRM_ALPHASTRING
int sprintf(const char *fmt,...) SYS_PRINTF_CHECK_ATTRIBUTE(2
GLint GLsizei GLsizei height
Definition: glcorearb.h:102
PRM_API PRM_Default PRMoneDefaults[]
double fpreal
Definition: SYS_Types.h:263
void setSampleRate(fpreal rate)
Definition: CL_Clip.h:87
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER T clip(const T &p, const Box< T > &box)
Definition: ImathBoxAlgo.h:89
SOP_BouncyAgent(OP_Network *net, const char *name, OP_Operator *op)
exint append(const UT_StringHolder &str)
Append a new string and return its index in the string array.
virtual bool setEntries(GA_Attribute *attrib, int n) const =0
#define GU_AGENT_LAYER_DEFAULT
Definition: GU_Agent.h:31
GLuint index
Definition: glcorearb.h:785
void setClipTime(GU_PrimPacked *prim, exint i, fpreal seconds)
static PRM_Template myTemplateList[]
exint append(void)
Definition: UT_Array.h:95
const GA_PrimitiveList & getPrimitiveList() const
Definition: GA_Detail.h:715
const char * buffer() const
static GU_AgentShapeLibPtr addLibrary(const char *name)
Create a new library using the given name.
virtual void setObjectCount(int nobj)=0
void bumpAllDataIds(GA_AttributeOwner owner)
Bumps all data IDs of attributes of the specified owner.
GLboolean r
Definition: glcorearb.h:1221
void clear()
Resets list to an empty list.
Definition: UT_Array.h:506
GA_Range getPrimitiveRange(const GA_PrimitiveGroup *group=0) const
Get a range of all primitives in the detail.
Definition: GA_Detail.h:1619
GA_Attribute * addPointCaptureAttribute(geo_NPairs n_pairs, CaptureType t=CAPTURE_BONE, GA_Storage s=GA_STORE_INVALID)
Add the (index, weight) point attribute for capture type t.
static GU_AgentLayerPtr addLayer(const char *unique_name, const GU_AgentRigConstPtr &rig, const GU_AgentShapeLibConstPtr &shapelib)
virtual const char * inputLabel(unsigned input_index) const
Method to provide input labels.
void translate(T dx, T dy, T dz=0.0f)
Definition: UT_Matrix4.h:608
SYS_API double sin(double x)
virtual OP_ERROR cookMySop(OP_Context &context)
Method to cook geometry for the SOP.
const char * getToken() const
Definition: PRM_Name.h:40
bool isParmDirty(int idx, fpreal t)
GA_Attribute * addStringTuple(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringHolder &name, int tuple_size, const UT_Options *creation_args=0, const GA_AttributeOptions *attribute_options=0, const GA_ReuseStrategy &reuse=GA_ReuseStrategy())