HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SOP_PointWave.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024
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  * The PointWave SOP. This SOP PointWaves the geometry onto a plane.
27  */
28 
29 #include "SOP_PointWave.h"
30 
31 #include <GU/GU_Detail.h>
32 #include <OP/OP_Operator.h>
33 #include <OP/OP_AutoLockInputs.h>
34 #include <OP/OP_OperatorTable.h>
35 #include <PRM/PRM_Include.h>
36 #include <UT/UT_DSOVersion.h>
37 #include <UT/UT_Matrix3.h>
38 #include <UT/UT_Matrix4.h>
39 #include <SYS/SYS_Math.h>
40 #include <stddef.h>
41 
42 using namespace HDK_Sample;
43 
44 void
46 {
47  table->addOperator(new OP_Operator(
48  "hdk_pointwave",
49  "Point Wave",
52  1,
53  1,
54  0));
55 }
56 
57 static PRM_Name names[] = {
58  PRM_Name("amp", "Amplitude"),
59  PRM_Name("phase", "Phase"),
60  PRM_Name("period", "Period"),
61 };
62 
68  PRM_Template(PRM_FLT_J, 1, &names[0], PRMoneDefaults, 0,
69  &PRMscaleRange),
70  PRM_Template(PRM_FLT_J, 1, &names[1], PRMzeroDefaults),
71  PRM_Template(PRM_FLT_J, 1, &names[2], PRMoneDefaults),
72  PRM_Template(),
73 };
74 
75 
76 OP_Node *
78 {
79  return new SOP_PointWave(net, name, op);
80 }
81 
83  : SOP_Node(net, name, op), myGroup(NULL)
84 {
85  // This indicates that this SOP manually manages its data IDs,
86  // so that Houdini can identify what attributes may have changed,
87  // e.g. to reduce work for the viewport, or other SOPs that
88  // check whether data IDs have changed.
89  // By default, (i.e. if this line weren't here), all data IDs
90  // would be bumped after the SOP cook, to indicate that
91  // everything might have changed.
92  // If some data IDs don't get bumped properly, the viewport
93  // may not update, or SOPs that check data IDs
94  // may not cook correctly, so be *very* careful!
96 }
97 
99 
100 OP_ERROR
102 {
103  // The SOP_Node::cookInputPointGroups() provides a good default
104  // implementation for just handling a point selection.
105  return cookInputPointGroups(
106  context, // This is needed for cooking the group parameter, and cooking the input if alone.
107  myGroup, // The group (or NULL) is written to myGroup if not alone.
108  alone, // This is true iff called outside of cookMySop to update handles.
109  // true means the group will be for the input geometry.
110  // false means the group will be for gdp (the working/output geometry).
111  true, // (default) true means to set the selection to the group if not alone and the highlight flag is on.
112  0, // (default) Parameter index of the group field
113  -1, // (default) Parameter index of the group type field (-1 since there isn't one)
114  true, // (default) true means that a pointer to an existing group is okay; false means group is always new.
115  false, // (default) false means new groups should be unordered; true means new groups should be ordered.
116  true, // (default) true means that all new groups should be detached, so not owned by the detail;
117  // false means that new point and primitive groups on gdp will be owned by gdp.
118  0 // (default) Index of the input whose geometry the group will be made for if alone.
119  );
120 }
121 
122 OP_ERROR
124 {
125  // We must lock our inputs before we try to access their geometry.
126  // OP_AutoLockInputs will automatically unlock our inputs when we return.
127  // NOTE: Don't call unlockInputs yourself when using this!
128  OP_AutoLockInputs inputs(this);
129  if (inputs.lock(context) >= UT_ERROR_ABORT)
130  return error();
131 
132  // Duplicate our incoming geometry with the hint that we only
133  // altered points. Thus, if our input was unchanged, we can
134  // easily roll back our changes by copying point values.
135  duplicatePointSource(0, context);
136 
137  fpreal t = context.getTime();
138 
139  // We evaluate our parameters outside the loop for speed. If we
140  // wanted local variable support, we'd have to do more setup
141  // (see SOP_Flatten) and also move these inside the loop.
142  float phase = PHASE(t);
143  float amp = AMP(t);
144  float period = PERIOD(t);
145 
146  if (error() >= UT_ERROR_ABORT)
147  return error();
148 
149  // Here we determine which groups we have to work on. We only
150  // handle point groups.
151  if (cookInputGroups(context) >= UT_ERROR_ABORT)
152  return error();
153 
154  GA_Offset ptoff;
155  GA_FOR_ALL_GROUP_PTOFF(gdp, myGroup, ptoff)
156  {
157  UT_Vector3 p = gdp->getPos3(ptoff);
158 
159  p.y() += SYSsin( (p.x() / period + phase) * M_PI * 2 ) * amp;
160 
161  gdp->setPos3(ptoff, p);
162  }
163 
164  // If we've modified P, and we're managing our own data IDs,
165  // we must bump the data ID for P.
166  if (!myGroup || !myGroup->isEmpty())
167  gdp->getP()->bumpDataId();
168 
169  return error();
170 }
SYS_FORCE_INLINE void bumpDataId()
Definition: GA_Attribute.h:306
virtual OP_ERROR error()
PRM_API const PRM_Type PRM_STRING
OP_ERROR lock(OP_Context &context)
Locks all inputs.
static OP_Node * myConstructor(OP_Network *, const char *, OP_Operator *)
Definition: SOP_PointWave.C:77
fpreal getTime() const
Definition: OP_Context.h:62
#define M_PI
Definition: fmath.h:90
static PRM_SpareData * getGroupSelectButton(GA_GroupType group_type, const char *group_type_parm=NULL, int input_index=0, PRM_SpareData *merge_spare_data=NULL, const char *assoc_groups=NULL, GroupSelectAsOrdered ordered=GroupSelectAsOrdered::AUTO, const char *use_name_attr=nullptr, const char *select_script=nullptr)
OP_ERROR cookMySop(OP_Context &context) override
Method to cook geometry for the SOP.
GA_Attribute * getP()
Convenience method to access the P attribute.
Definition: GA_Detail.h:164
UT_ErrorSeverity
Definition: UT_Error.h:25
SOP_PointWave(OP_Network *net, const char *name, OP_Operator *op)
Definition: SOP_PointWave.C:82
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
SYS_FORCE_INLINE UT_Vector3 getPos3(GA_Offset ptoff) const
The ptoff passed is the point offset.
Definition: GA_Detail.h:185
static PRM_ChoiceList pointGroupMenu
Definition: SOP_Node.h:1190
OP_ERROR duplicatePointSource(unsigned index, OP_Context &ctx, GU_Detail *gdp, bool clean=true, bool wattrib=true, bool *fully=0)
GA_Size GA_Offset
Definition: GA_Types.h:641
OP_ERROR cookInputGroups(OP_Context &context, int alone=0) override
SOP_NodeFlags mySopFlags
Definition: SOP_Node.h:1625
OP_ERROR cookInputPointGroups(OP_Context &context, const GA_PointGroup *&group, bool alone=false, bool do_selection=true, int parm_index=0, int group_type_index=-1, bool allow_reference=true, bool ordered=false, bool detached=true, int input_index=0)
See cookInputPrimitiveGroups.
PRM_API PRM_Range PRMscaleRange
GLuint const GLchar * name
Definition: glcorearb.h:786
PRM_API PRM_Name PRMgroupName
PRM_API const PRM_Type PRM_FLT_J
GLenum GLenum GLsizei void * table
Definition: glad.h:5129
void setManagesDataIDs(bool onOff)
Definition: SOP_NodeFlags.h:36
GLdouble t
Definition: glad.h:2397
GU_Detail * gdp
Definition: SOP_Node.h:1622
void newSopOperator(OP_OperatorTable *table)
Definition: SOP_PointWave.C:45
PRM_API PRM_Default PRMoneDefaults[]
SYS_FORCE_INLINE void setPos3(GA_Offset ptoff, const UT_Vector3 &pos)
Set P from a UT_Vector3.
Definition: GA_Detail.h:237
#define GA_FOR_ALL_GROUP_PTOFF(gdp, grp, ptoff)
Definition: GA_GBMacros.h:96
fpreal64 fpreal
Definition: SYS_Types.h:277
static PRM_Template myTemplateList[]
Definition: SOP_PointWave.h:44
SYS_FORCE_INLINE bool isEmpty() const
Query whether the group is empty of primary elements.
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector3.h:665
PRM_API PRM_Default PRMzeroDefaults[]
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:663