HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
COP2_SampleGenerator.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  * Constant SampleGenerator COP
27  */
28 #include <UT/UT_DSOVersion.h>
29 
30 #include <SYS/SYS_Math.h>
31 #include <UT/UT_SysClone.h>
32 
33 #include <OP/OP_OperatorTable.h>
34 
35 #include <PRM/PRM_Include.h>
36 #include <PRM/PRM_Parm.h>
37 
38 #include <TIL/TIL_Plane.h>
39 #include <TIL/TIL_Tile.h>
40 #include "COP2_SampleGenerator.h"
41 
42 using namespace HDK_Sample;
43 
44 COP2_GENERATOR_SWITCHER(2, "HDK Sample Generator");
45 
46 static PRM_Name names[] =
47 {
48  PRM_Name("seed", "Seed"),
49  PRM_Name("ampl", "Amplitude"),
50 };
51 
54 {
56 
59 
60  PRM_Template(),
61 };
62 
66 
69 
70 
71 OP_Node *
73  const char *name,
74  OP_Operator *op)
75 {
76  return new COP2_SampleGenerator(net, name, op);
77 }
78 
79 COP2_SampleGenerator::COP2_SampleGenerator(OP_Network *parent,
80  const char *name,
81  OP_Operator *entry)
82  : COP2_Generator(parent, name, entry)
83 {
84 }
85 
87 {
88 }
89 
90 // -----------------------------------------------------------------------
91 
92 /// This method computes the resolution, frame range and planes & formats
93 /// used during the cook. All of these parms are non-animatable. It is called
94 /// first during a cook, or when the information is requested from a node.
95 /// Just because cookSequenceInfo is called, it does not mean that a cook is
96 /// about to start.
99 {
100  // If you want the controls in the Image/Sequence pages to
101  // affect planes, format, res, range, use this parent class method.
102  // You can always override them after the call.
104 
105  //// ***** Other examples ***********
106  //// Manual setup of sequences
107 
108  //// 1. Clear out any previous values.
109  // mySequence.reset();
110 
111  //// (optional) To copy an input's sequence information:
112  // const TIL_Sequence *seq = inputInfo ( 0 ); // input #
113  // if(seq)
114  // mySequence = *seq;
115  // else
116  // { error = UT_ERROR_ABORT; return &mySequence; } // should pop an err
117 
118  //// 2. Set up frame range ****************
119 
120  //// Do you want a single image only? ie, time invariant.
121  // mySequence.setSingleImage(1);
122 
123  //// otherwise, animations look like (sample values only):
124  // mySequence.setSingleImage(0);
125  // mySequence.setStart(1);
126  // mySequence.setLength(300);
127  // mySequence.setFrameRate(30);
128 
129 
130  //// 3. Set up the Resolution **************
131 
132  //// Fairly straightforward - X Y dimensions. Must be at least 1. Don't
133  //// worry about reduced cooking res's - they are handled automatically.
134  // mySequence.setRes(500, 400);
135  // mySequence.setAspectRatio(1.0f); // x/y (ie, 2: pixel is twice as wide as
136  // it is tall)
137 
138  //// 4. Planes & Data formats ****************************
139  //// Set up the actual planes we'll use. We can create up to 4000, but each
140  //// must have a unique plane name.
141 
142  //// if you'd like to call COP2_Generator to setup the res, range, etc.,
143  //// but want complete control over the planes yourself, call:
144 
145  // mySequence.clearAllPlanes();
146 
147  //// which will remove any planes added by COP2_Generator
148 
149 
150  //// To add planes, use:
151 
152  // mySequence.addPlane("name_of_plane", TILE_[format], "name_of_comp",...)
153 
154  //// plane names recognized by Halo:
155  //// getColorPlaneName()
156  //// getAlphaPlaneName()
157  //// getMaskPlaneName()
158  //// getDepthPlaneName()
159  //// getLumPlaneName()
160  //// getBumpPlaneName()
161  //// getPointPlaneName()
162  //// getNormalPlaneName()
163  //// getVelocityPlaneName()
164  //// Other names can be used as well, but other Nodes won't recognize it
165  //// as anything special.
166 
167  //// format can be TILE_INT8, TILE_INT16, TILE_INT32, TILE_FLOAT32.
168  //// To use black/white points for int formats, call setBlackWhitePoints()
169  //// on the returned plane from addPlane(). FP does not support B/W points.
170 
171  //// components - can be anything descriptive (r,g,b, x,y,z, u,v).
172  //// Halo doesn't care about what the component are names at all.
173  //// The number of strings defines the vector size of the plane (up to 4).
174  //// if no components are specified, the plane is assumed to be Scalar.
175 
176  //TIL_Plane *plane;
177 
178  //// FP color plane, vector size 3 with components named r,g,b.
179  //plane = mySequence.addPlane( getColorPlaneName(), TILE_FLOAT32,
180  // "r","g","b");
181 
182  //// 8 bit alpha plane, scalar.
183  //plane = mySequence.addPlane( getAlphaPlaneName(), TILE_INT8 );
184  // plane->setBlackWhitePoints(16, 240); // for 8 bit with a bit of
185  // head/foot room, for example
186 
187  //// Some other plane examples:
188 
189  // plane = mySequence.addPlane( getBumpPlaneName(), TILE_INT16, "u","v");
190  // plane->setBlackWhitePoints(32768, 65535); // dynamic range ~= -1 to 1
191 
192  // mySequence.addPlane( getDepthPlaneName(), TILE_FLOAT32);
193 
194  // mySequence.addPlane( getPointPlaneName(), TILE_FLOAT32, "x","y","z");
195 
196  //// ****** End examples *******
197 
198  // done.
199  return &mySequence;
200 }
201 
202 
203 // ** newContextData()
204 // This method is used to create a custom context for your node. If you need
205 // to evaluate animated parms, do it here and stash the values in your context
206 // data. All context data classes must derive from COP2_ContextData (see .h
207 // file for class def)
208 
209 // If you have all static parms, like menus or toggles, you can evaluate them
210 // in cookSequenceInfo() instead, if you like.
211 
212 // The context data is also useful for holding scratch data arrays.
213 
214 // By default, a context is created for each different time and each different
215 // resolution. You can also cause it to create them if the plane differs, or
216 // the thread differs (if a plane or res variable is used in an expression, it
217 // will automatically create a new context data for you if plane or res
218 // changes). To controls the creation of contexts, override the virtuals:
219 //
220 // virtual bool createPerPlane() const { return false; }
221 // virtual bool createPerRes() const { return true; }
222 // virtual bool createPerTime() const { return true; }
223 // virtual bool createPerThread() const { return false; }
224 
225 // in your custom COP2_ContextData class.
226 
229  int /*arrayindex*/,
230  float t, int /*xsize*/, int /*ysize*/,
231  int /*thread*/, int /*max_num_threads*/)
232 {
233  // create one of my context data objects.
235 
236  // stashing some parm values for the cook in my context data.
237  AMP(data->myAmp, t);
238  data->mySeed = SEED(t);
239 
240  return data;
241 }
242 
243 // ** generateTile()
244 // This method cooks a tile of the full image. A tile is a rectangular region
245 // of the image for a specific component of a specific plane. This means that
246 // all vectors' data is stored non-interleaved, one component per tile.
247 
248 // Before proceeding with your cook, you may need to check the:
249 // - plane you are being requested to cook (context.myPlane)
250 // - the resolution you are being cooked at (context.myXres, context.myYres)
251 // - the time you are being cooked at (context.getTime())
252 // - the area the tile occupies (tiles->myX1, tiles->myY1) -
253 // (tiles->myX2, tiles->myY2)
254 
255 // You may not be asked to cook all the tiles in the image, and you may not
256 // be asked to cook all the planes. Cooking is done on an on-demand basis.
257 // The order you are asked to cook tiles in is undefined.
258 
259 // The TIL_TileList passed to you contains 1-4 tiles, depending on the # of
260 // components in that plane. Some of these components may already be cached,
261 // so use FOR_EACH_UNCOOKED_TILE(tiles, itr) to iterate through only dirty
262 // tiles or TILE_VECTOR4(tiles, t1,t2,t3,t4) to assign the dirty tiles to
263 // TIL_Tile *t1,*t2,*t3,*t4. Non-dirty or non-existant tiles will be assigned
264 // NULL to the TIL_Tile ptr.
265 
266 // Tiles are not pre-cleared for you. You must write to each pixel in the tile.
267 
268 // THREAD WARNING: This method is called simultaneously in different threads.
269 // Don't do un-threadsafe stuff here, like writing to static buffers.
270 
271 OP_ERROR
273 {
274  // retrieve my context data created for this plane/res/time/thread
275  // by my newContextData method.
277  static_cast<cop2_SampleGeneratorData *>( context.data() );
278 
279  int i, ti;
280  TIL_Tile * itr;
281  unsigned seed;
282  const float *amp = data->myAmp.data();
283 
284  // alloc some temp space for our values. If we know that we're always using
285  // FP, we could just write the values into the tiles directly using
286  // dest = (float *) itr->getImageData();
287  float *dest = new float[tiles->mySize];
288 
289  FOR_EACH_UNCOOKED_TILE(tiles, itr, ti)
290  {
291  // initial seed value based on lower left corner position & tile index.
292  seed = ((unsigned) data->mySeed * 4 + ti)
293  * (context.myXres * context.myYres) +
294  tiles->myX1 + tiles->myY1 * context.myXres;
295 
296  // tiles->mySize is the # of pixels in the tile.
297  for(i=0; i<tiles->mySize; i++)
298  dest[i] = SYSrandom(seed) * amp[ti];
299 
300  // write the values back to the tile using a convenience method.
301  // not necessary if we used dest = (float *) itr->getImageData() above.
302  writeFPtoTile(tiles, dest, ti);
303  }
304 
305  delete [] dest;
306 
307  return error();
308 }
309 
311 {
312  // This operator flags itself as a generator taking zero or one inputs.
313  // The optional input is the mask.
314  table->addOperator(new OP_Operator("hdk_samplegen", // node name
315  "HDK Sample Generator", // pretty name
318  0, // min inputs
319  1, // max inputs
322 }
void writeFPtoTile(TIL_TileList *tilelist, float *&src, int index)
void newCop2Operator(OP_OperatorTable *table)
TIL_Sequence mySequence
Definition: COP2_Node.h:1345
GLboolean * data
Definition: glcorearb.h:131
TIL_Sequence * cookSequenceInfo(OP_ERROR &error) override
*}
OP_ERROR error() override
Definition: COP2_Node.h:483
COP2_GENERATOR_SWITCHER(2,"HDK Sample Generator")
COP2_ContextData * newContextData(const TIL_Plane *, int, float t, int xres, int yres, int thread, int max_threads) override
Evaluate parms and stash data for cooking in a COP2_ContextData object.
#define FOR_EACH_UNCOOKED_TILE(list, tile, i)
Definition: TIL_Defines.h:192
#define OP_FLAG_GENERATOR
Definition: OP_Operator.h:82
UT_ErrorSeverity
Definition: UT_Error.h:25
static OP_VariablePair myVariablePair
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
Simple COP generator example for the HDK.
static OP_VariablePair myVariablePair
Definition: COP2_Node.h:663
PRM_API const PRM_Type PRM_INT_J
static OP_TemplatePair myTemplatePair
PRM_API const PRM_Type PRM_RGB_J
Data class to hold parm values and data for COP2_SampleGenerator.
COP2_ContextData * data()
GLuint const GLchar * name
Definition: glcorearb.h:786
GLenum GLenum GLsizei void * table
Definition: glad.h:5129
PRM_API const PRM_Type PRM_SWITCHER
GLdouble t
Definition: glad.h:2397
#define TOOL_PARM
Definition: COP2_Common.h:26
PRM_API PRM_Default PRMoneDefaults[]
PRM_API PRM_Name PRMswitcherName
static OP_Node * myConstructor(OP_Network *, const char *, OP_Operator *)
static OP_TemplatePair myTemplatePair
constexpr SYS_FORCE_INLINE const T * data() const noexcept
Definition: UT_Vector4.h:224
OP_ERROR generateTile(COP2_Context &context, TIL_TileList *tilelist) override
Create the image data for a single tile list - multithreaded call.
TIL_Sequence * cookSequenceInfo(OP_ERROR &error) override
Definition: format.h:895