00001 /* 00002 * Copyright (c) 2012 00003 * Side Effects Software Inc. All rights reserved. 00004 * 00005 * Redistribution and use of Houdini Development Kit samples in source and 00006 * binary forms, with or without modification, are permitted provided that the 00007 * following conditions are met: 00008 * 1. Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * 2. The name of Side Effects Software may not be used to endorse or 00011 * promote products derived from this software without specific prior 00012 * written permission. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 00015 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00017 * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00019 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 00020 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00021 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00022 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 00023 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 *---------------------------------------------------------------------------- 00026 * Constant SampleGenerator COP 00027 */ 00028 #include <UT/UT_DSOVersion.h> 00029 00030 #include <UT/UT_Math.h> 00031 #include <UT/UT_SysClone.h> 00032 00033 #include <OP/OP_OperatorTable.h> 00034 00035 #include <PRM/PRM_Include.h> 00036 #include <PRM/PRM_Parm.h> 00037 00038 #include <TIL/TIL_Plane.h> 00039 #include <TIL/TIL_Tile.h> 00040 #include "COP2_SampleGenerator.h" 00041 00042 using namespace HDK_Sample; 00043 00044 COP_GENERATOR_SWITCHER(2, "HDK Sample Generator"); 00045 00046 static PRM_Name names[] = 00047 { 00048 PRM_Name("seed", "Seed"), 00049 PRM_Name("ampl", "Amplitude"), 00050 }; 00051 00052 PRM_Template 00053 COP2_SampleGenerator::myTemplateList[] = 00054 { 00055 PRM_Template(PRM_SWITCHER, 3, &PRMswitcherName, switcher), 00056 00057 PRM_Template(PRM_INT_J, TOOL_PARM, 1, &names[0], PRMoneDefaults), 00058 PRM_Template(PRM_RGB_J, TOOL_PARM, 4, &names[1], PRMoneDefaults), 00059 00060 PRM_Template(), 00061 }; 00062 00063 OP_TemplatePair COP2_SampleGenerator::myTemplatePair( 00064 COP2_SampleGenerator::myTemplateList, 00065 &COP2_Generator::myTemplatePair ); 00066 00067 OP_VariablePair COP2_SampleGenerator::myVariablePair(0, 00068 &COP2_Node::myVariablePair ); 00069 00070 00071 OP_Node * 00072 COP2_SampleGenerator::myConstructor( OP_Network *net, 00073 const char *name, 00074 OP_Operator *op) 00075 { 00076 return new COP2_SampleGenerator(net, name, op); 00077 } 00078 00079 COP2_SampleGenerator::COP2_SampleGenerator(OP_Network *parent, 00080 const char *name, 00081 OP_Operator *entry) 00082 : COP2_Generator(parent, name, entry) 00083 { 00084 } 00085 00086 COP2_SampleGenerator::~COP2_SampleGenerator() 00087 { 00088 } 00089 00090 // ----------------------------------------------------------------------- 00091 00092 /// This method computes the resolution, frame range and planes & formats 00093 /// used during the cook. All of these parms are non-animatable. It is called 00094 /// first during a cook, or when the information is requested from a node. 00095 /// Just because cookSequenceInfo is called, it does not mean that a cook is 00096 /// about to start. 00097 TIL_Sequence * 00098 COP2_SampleGenerator::cookSequenceInfo(OP_ERROR & error) 00099 { 00100 // If you want the controls in the Image/Sequence pages to 00101 // affect planes, format, res, range, use this parent class method. 00102 // You can always override them after the call. 00103 COP2_Generator::cookSequenceInfo(error); 00104 00105 //// ***** Other examples *********** 00106 //// Manual setup of sequences 00107 00108 //// 1. Clear out any previous values. 00109 // mySequence.reset(); 00110 00111 //// (optional) To copy an input's sequence information: 00112 // const TIL_Sequence *seq = inputInfo ( 0 ); // input # 00113 // if(seq) 00114 // mySequence = *seq; 00115 // else 00116 // { error = UT_ERROR_ABORT; return &mySequence; } // should pop an err 00117 00118 //// 2. Set up frame range **************** 00119 00120 //// Do you want a single image only? ie, time invariant. 00121 // mySequence.setSingleImage(1); 00122 00123 //// otherwise, animations look like (sample values only): 00124 // mySequence.setSingleImage(0); 00125 // mySequence.setStart(1); 00126 // mySequence.setLength(300); 00127 // mySequence.setFrameRate(30); 00128 00129 00130 //// 3. Set up the Resolution ************** 00131 00132 //// Fairly straightforward - X Y dimensions. Must be at least 1. Don't 00133 //// worry about reduced cooking res's - they are handled automatically. 00134 // mySequence.setRes(500, 400); 00135 // mySequence.setAspectRatio(1.0f); // x/y (ie, 2: pixel is twice as wide as 00136 // it is tall) 00137 00138 //// 4. Planes & Data formats **************************** 00139 //// Set up the actual planes we'll use. We can create up to 4000, but each 00140 //// must have a unique plane name. 00141 00142 //// if you'd like to call COP2_Generator to setup the res, range, etc., 00143 //// but want complete control over the planes yourself, call: 00144 00145 // mySequence.clearAllPlanes(); 00146 00147 //// which will remove any planes added by COP2_Generator 00148 00149 00150 //// To add planes, use: 00151 00152 // mySequence.addPlane("name_of_plane", TILE_[format], "name_of_comp",...) 00153 00154 //// plane names recognized by Halo: 00155 //// getColorPlaneName() 00156 //// getAlphaPlaneName() 00157 //// getMaskPlaneName() 00158 //// getDepthPlaneName() 00159 //// getLumPlaneName() 00160 //// getBumpPlaneName() 00161 //// getPointPlaneName() 00162 //// getNormalPlaneName() 00163 //// getVelocityPlaneName() 00164 //// Other names can be used as well, but other Nodes won't recognize it 00165 //// as anything special. 00166 00167 //// format can be TILE_INT8, TILE_INT16, TILE_INT32, TILE_FLOAT32. 00168 //// To use black/white points for int formats, call setBlackWhitePoints() 00169 //// on the returned plane from addPlane(). FP does not support B/W points. 00170 00171 //// components - can be anything descriptive (r,g,b, x,y,z, u,v). 00172 //// Halo doesn't care about what the component are names at all. 00173 //// The number of strings defines the vector size of the plane (up to 4). 00174 //// if no components are specified, the plane is assumed to be Scalar. 00175 00176 //TIL_Plane *plane; 00177 00178 //// FP color plane, vector size 3 with components named r,g,b. 00179 //plane = mySequence.addPlane( getColorPlaneName(), TILE_FLOAT32, 00180 // "r","g","b"); 00181 00182 //// 8 bit alpha plane, scalar. 00183 //plane = mySequence.addPlane( getAlphaPlaneName(), TILE_INT8 ); 00184 // plane->setBlackWhitePoints(16, 240); // for 8 bit with a bit of 00185 // head/foot room, for example 00186 00187 //// Some other plane examples: 00188 00189 // plane = mySequence.addPlane( getBumpPlaneName(), TILE_INT16, "u","v"); 00190 // plane->setBlackWhitePoints(32768, 65535); // dynamic range ~= -1 to 1 00191 00192 // mySequence.addPlane( getDepthPlaneName(), TILE_FLOAT32); 00193 00194 // mySequence.addPlane( getPointPlaneName(), TILE_FLOAT32, "x","y","z"); 00195 00196 //// ****** End examples ******* 00197 00198 // done. 00199 return &mySequence; 00200 } 00201 00202 00203 // ** newContextData() 00204 // This method is used to create a custom context for your node. If you need 00205 // to evaluate animated parms, do it here and stash the values in your context 00206 // data. All context data classes must derive from COP2_ContextData (see .h 00207 // file for class def) 00208 00209 // If you have all static parms, like menus or toggles, you can evaluate them 00210 // in cookSequenceInfo() instead, if you like. 00211 00212 // The context data is also useful for holding scratch data arrays. 00213 00214 // By default, a context is created for each different time and each different 00215 // resolution. You can also cause it to create them if the plane differs, or 00216 // the thread differs (if a plane or res variable is used in an expression, it 00217 // will automatically create a new context data for you if plane or res 00218 // changes). To controls the creation of contexts, override the virtuals: 00219 // 00220 // virtual bool createPerPlane() const { return false; } 00221 // virtual bool createPerRes() const { return true; } 00222 // virtual bool createPerTime() const { return true; } 00223 // virtual bool createPerThread() const { return false; } 00224 00225 // in your custom COP2_ContextData class. 00226 00227 COP2_ContextData * 00228 COP2_SampleGenerator::newContextData(const TIL_Plane * /*planename*/, 00229 int /*arrayindex*/, 00230 float t, int /*xsize*/, int /*ysize*/, 00231 int /*thread*/, int /*max_num_threads*/) 00232 { 00233 // create one of my context datas. 00234 cop2_SampleGeneratorData *data = new cop2_SampleGeneratorData; 00235 00236 // stashing some parm values for the cook in my context data. 00237 AMP(data->myAmp, t); 00238 data->mySeed = SEED(t); 00239 00240 return data; 00241 } 00242 00243 // ** generateTile() 00244 // This method cooks a tile of the full image. A tile is a rectangular region 00245 // of the image for a specific component of a specific plane. This means that 00246 // all vectors' data is stored non-interleaved, one component per tile. 00247 00248 // Before proceeding with your cook, you may need to check the: 00249 // - plane you are being requested to cook (context.myPlane) 00250 // - the resolution you are being cooked at (context.myXres, context.myYres) 00251 // - the time you are being cooked at (context.myTime) 00252 // - the area the tile occupies (tiles->myX1, tiles->myY1) - 00253 // (tiles->myX2, tiles->myY2) 00254 00255 // You may not be asked to cook all the tiles in the image, and you may not 00256 // be asked to cook all the planes. Cooking is done on an on-demand basis. 00257 // The order you are asked to cook tiles in is undefined. 00258 00259 // The TIL_TileList passed to you contains 1-4 tiles, depending on the # of 00260 // components in that plane. Some of these components may already be cached, 00261 // so use FOR_EACH_UNCOOKED_TILE(tiles, itr) to iterate through only dirty 00262 // tiles or TILE_VECTOR4(tiles, t1,t2,t3,t4) to assign the dirty tiles to 00263 // TIL_Tile *t1,*t2,*t3,*t4. Non-dirty or non-existant tiles will be assigned 00264 // NULL to the TIL_Tile ptr. 00265 00266 // Tiles are not pre-cleared for you. You must write to each pixel in the tile. 00267 00268 // THREAD WARNING: This method is called simultaneously in different threads. 00269 // Don't do un-threadsafe stuff here, like writing to static buffers. 00270 00271 OP_ERROR 00272 COP2_SampleGenerator::generateTile(COP2_Context &context, TIL_TileList *tiles) 00273 { 00274 // retrieve my context data created for this plane/res/time/thread 00275 // by my newContextData method. 00276 cop2_SampleGeneratorData *data = 00277 static_cast<cop2_SampleGeneratorData *>( context.data() ); 00278 00279 int i, ti; 00280 TIL_Tile * itr; 00281 unsigned seed; 00282 const float *amp = data->myAmp.data(); 00283 00284 // alloc some temp space for our values. If we know that we're always using 00285 // FP, we could just write the values into the tiles directly using 00286 // dest = (float *) itr->getImageData(); 00287 float *dest = new float[tiles->mySize]; 00288 00289 FOR_EACH_UNCOOKED_TILE(tiles, itr, ti) 00290 { 00291 // initial seed value based on lower left corner position & tile index. 00292 seed = ((unsigned) data->mySeed * 4 + ti) 00293 * (context.myXres * context.myYres) + 00294 tiles->myX1 + tiles->myY1 * context.myXres; 00295 00296 // tiles->mySize is the # of pixels in the tile. 00297 for(i=0; i<tiles->mySize; i++) 00298 dest[i] = UTrandom(seed) * amp[ti]; 00299 00300 // write the values back to the tile using a convenience method. 00301 // not necessary if we used dest = (float *) itr->getImageData() above. 00302 writeFPtoTile(tiles, dest, ti); 00303 } 00304 00305 delete dest; 00306 00307 return error(); 00308 } 00309 00310 00311 /// install the cop. 00312 void newCop2Operator(OP_OperatorTable *table) 00313 { 00314 // This operator flags itself as a generator taking zero or one inputs. 00315 // The optional input is the mask. 00316 table->addOperator(new OP_Operator("hdk_samplegen", // node name 00317 "HDK Sample Generator", // pretty name 00318 COP2_SampleGenerator::myConstructor, 00319 &COP2_SampleGenerator::myTemplatePair, 00320 0, // min inputs 00321 1, // max inputs 00322 &COP2_SampleGenerator::myVariablePair, 00323 OP_FLAG_GENERATOR)); 00324 }
1.5.9