00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <UT/UT_DSOVersion.h>
00031 #include <OP/OP_OperatorTable.h>
00032 #include <PRM/PRM_Include.h>
00033
00034 #include <SYS/SYS_Floor.h>
00035 #include <SYS/SYS_Math.h>
00036
00037 #include <TIL/TIL_Plane.h>
00038 #include <TIL/TIL_Region.h>
00039 #include <TIL/TIL_Tile.h>
00040 #include <COP2/COP2_CookAreaInfo.h>
00041 #include "COP2_MultiInputWipe.h"
00042
00043 using namespace HDK_Sample;
00044
00045 COP_MULTI_SWITCHER(5, "Blend");
00046
00047 static PRM_Name names[] =
00048 {
00049 PRM_Name("fadera", "A Fader"),
00050 PRM_Name("faderb", "B Fader"),
00051 PRM_Name("boostval", "Overexposure Boost"),
00052 PRM_Name("bloomblur", "Bloom Blur"),
00053 PRM_Name("fademode", "Fade Rate"),
00054 };
00055
00056 #define FADE_LINEAR 0
00057 #define FADE_SQUARE 1
00058 #define FADE_ROOT 2
00059 static PRM_Name fadeItems[] =
00060 {
00061 PRM_Name("linear", "Linear"),
00062 PRM_Name("squared", "Squared"),
00063 PRM_Name("root", "Square Root"),
00064 PRM_Name(0),
00065 };
00066 static PRM_ChoiceList fadeMenu((PRM_ChoiceListType)
00067 (PRM_CHOICELIST_EXCLUSIVE | PRM_CHOICELIST_REPLACE), fadeItems);
00068
00069
00070 static PRM_Range wipeRange(PRM_RANGE_RESTRICTED, 0.0f,
00071 PRM_RANGE_RESTRICTED, 1.0f);
00072 static PRM_Range boostRange(PRM_RANGE_UI, 0.0f, PRM_RANGE_UI, 1.0f);
00073 static PRM_Range blurRange(PRM_RANGE_RESTRICTED, 0.0f, PRM_RANGE_UI, 20.0f);
00074 static PRM_Default boostValue(0.9);
00075 static PRM_Default boostBlur(9);
00076
00077 PRM_Template
00078 COP2_MultiInputWipe::myTemplateList[] =
00079 {
00080 PRM_Template(PRM_SWITCHER, 2, &PRMswitcherName, switcher),
00081
00082
00083 PRM_Template(PRM_FLT, TOOL_PARM, 1, &names[0], PRMoneDefaults, 0,
00084 &wipeRange),
00085 PRM_Template(PRM_FLT, TOOL_PARM, 1, &names[1], PRMzeroDefaults, 0,
00086 &wipeRange),
00087 PRM_Template(PRM_FLT, TOOL_PARM, 1, &names[2], &boostValue, 0,
00088 &boostRange),
00089 PRM_Template(PRM_FLT, TOOL_PARM, 1, &names[3], &boostBlur, 0,
00090 &blurRange),
00091 PRM_Template(PRM_ORD, POPUP_PARM, 1, &names[4], PRMoneDefaults,
00092 &fadeMenu),
00093 PRM_Template(),
00094 };
00095
00096 OP_TemplatePair COP2_MultiInputWipe::myTemplatePair(
00097 COP2_MultiInputWipe::myTemplateList,
00098 &COP2_MultiBase::myTemplatePair );
00099
00100 OP_VariablePair COP2_MultiInputWipe::myVariablePair( 0,
00101 &COP2_Node::myVariablePair );
00102
00103 const char * COP2_MultiInputWipe::myInputLabels[] =
00104 {
00105 "Wipe A",
00106 "Wipe B",
00107 0
00108 };
00109
00110 OP_Node *
00111 COP2_MultiInputWipe::myConstructor( OP_Network *net,
00112 const char *name,
00113 OP_Operator *op)
00114 {
00115 return new COP2_MultiInputWipe(net, name, op);
00116 }
00117
00118 COP2_MultiInputWipe::COP2_MultiInputWipe(OP_Network *parent,
00119 const char *name,
00120 OP_Operator *entry)
00121 : COP2_MultiBase(parent, name, entry)
00122 {
00123 }
00124
00125 COP2_MultiInputWipe::~COP2_MultiInputWipe()
00126 {
00127 }
00128
00129 class cop2_MultiInputWipeData : public COP2_ContextData
00130 {
00131 public:
00132 cop2_MultiInputWipeData() {}
00133 virtual ~cop2_MultiInputWipeData() {}
00134
00135
00136 float myFaderA;
00137 float myFaderB;
00138 float myBoostA;
00139 float myBoostB;
00140 int myBlurRadA;
00141 int myBlurRadB;
00142 float myBlurA;
00143 float myBlurB;
00144 bool myPassA;
00145 bool myPassB;
00146 };
00147
00148 COP2_ContextData *
00149 COP2_MultiInputWipe::newContextData(const TIL_Plane *, int , float t,
00150 int xres, int , int , int )
00151 {
00152 cop2_MultiInputWipeData *data = new cop2_MultiInputWipeData();
00153 int fademode;
00154 float blur;
00155 float boost;
00156
00157
00158 data->myFaderA = evalFloat("fadera",0,t);
00159 data->myFaderB = evalFloat("faderb",0,t);
00160
00161 fademode = evalInt("fademode", 0, t);
00162
00163 if(fademode == FADE_SQUARE)
00164 {
00165 data->myFaderA *= data->myFaderA;
00166 data->myFaderB *= data->myFaderB;
00167 }
00168 else if(fademode == FADE_ROOT)
00169 {
00170 data->myFaderA = SYSsqrt(data->myFaderA);
00171 data->myFaderB = SYSsqrt(data->myFaderB);
00172 }
00173
00174
00175 data->myPassA = (data->myFaderA == 1.0f && data->myFaderB == 0.0f);
00176 data->myPassB = (data->myFaderB == 1.0f && data->myFaderA == 0.0f);
00177
00178
00179 boost = evalFloat("boostval", 0, t) * 0.5f;
00180 data->myBoostA = data->myFaderB * boost;
00181 data->myBoostB = data->myFaderA * boost;
00182
00183
00184 blur = evalFloat("bloomblur", 0, t) * getXScaleFactor(xres);
00185
00186
00187 data->myBlurA = data->myFaderB * blur;
00188 data->myBlurB = data->myFaderA * blur;
00189 data->myBlurRadA = (int)SYSceil(data->myBlurA * 0.5f);
00190 data->myBlurRadB = (int)SYSceil(data->myBlurB * 0.5f);
00191
00192 return data;
00193 }
00194
00195
00196 void
00197 COP2_MultiInputWipe::computeImageBounds(COP2_Context &context)
00198 {
00199 cop2_MultiInputWipeData *data =
00200 static_cast<cop2_MultiInputWipeData *>(context.data());
00201 bool init = false;
00202 int x1,y1,x2,y2;
00203 int ix1, ix2, iy1, iy2;
00204
00205 x1 = 0;
00206 y1 = 0;
00207 x2 = context.myXres-1;
00208 y2 = context.myYres-1;
00209
00210
00211 for(int i=0; i<nInputs(); i++)
00212 {
00213 if(getInputBounds(i, context, ix1, iy1, ix2, iy2))
00214 {
00215 if(!init)
00216 {
00217 x1 = ix1;
00218 y1 = iy1;
00219 x2 = ix2;
00220 y2 = iy2;
00221 init = true;
00222 }
00223 else
00224 {
00225 if(ix1 < x1) x1 = ix1;
00226 if(ix2 > x2) x2 = ix2;
00227 if(iy1 < y1) y1 = iy1;
00228 if(iy2 > y2) y2 = iy2;
00229 }
00230 }
00231 }
00232
00233
00234 if(!data->myPassA && !data->myPassB)
00235 {
00236 int brad = SYSmax(data->myBlurRadA, data->myBlurRadB);
00237 x1 -= brad;
00238 y1 -= brad;
00239 x2 += brad;
00240 y2 += brad;
00241 }
00242
00243 context.setImageBounds(x1,y1,x2,y2);
00244 }
00245
00246 void
00247 COP2_MultiInputWipe::getInputDependenciesForOutputArea(
00248 COP2_CookAreaInfo &output_area,
00249 const COP2_CookAreaList &input_areas,
00250 COP2_CookAreaList &needed_areas)
00251 {
00252 cop2_MultiInputWipeData *cdata;
00253 COP2_Context *context;
00254 COP2_CookAreaInfo *area;
00255
00256
00257 if (getBypass())
00258 {
00259 area = makeOutputAreaDependOnMyPlane(0, output_area, input_areas,
00260 needed_areas);
00261 return;
00262 }
00263
00264 context = output_area.getNodeContextData();
00265 cdata = static_cast<cop2_MultiInputWipeData *>(context->data());
00266
00267
00268 if(!cdata->myPassB)
00269 {
00270 area = makeOutputAreaDependOnMyPlane(0, output_area, input_areas,
00271 needed_areas);
00272
00273 if(area)
00274 area->expandNeededArea( cdata->myBlurRadA, cdata->myBlurRadA,
00275 cdata->myBlurRadA, cdata->myBlurRadA);
00276 }
00277
00278
00279 if(!cdata->myPassA)
00280 {
00281 area = makeOutputAreaDependOnMyPlane(1, output_area, input_areas,
00282 needed_areas);
00283 if(area)
00284 area->expandNeededArea( cdata->myBlurRadB, cdata->myBlurRadB,
00285 cdata->myBlurRadB, cdata->myBlurRadB);
00286 }
00287 }
00288
00289 int
00290 COP2_MultiInputWipe::passThrough(COP2_Context &context,
00291 const TIL_Plane *plane, int,
00292 int, float t,
00293 int xstart, int ystart)
00294 {
00295 cop2_MultiInputWipeData *data =
00296 static_cast<cop2_MultiInputWipeData *>(context.data());
00297 const TIL_Sequence *inputseq = 0;
00298
00299
00300
00301 if(data->myPassA)
00302 inputseq = inputInfo(0);
00303 else if(data->myPassB)
00304 inputseq = inputInfo(1);
00305
00306 if(inputseq)
00307 {
00308
00309
00310 const TIL_Plane *inputplane = inputseq->getPlane(plane->getName());
00311 if(inputplane)
00312 {
00313 int xres,yres;
00314 int ixres, iyres;
00315
00316 mySequence.getRes(xres,yres);
00317 inputseq->getRes(ixres,iyres);
00318
00319 if(plane->isCompatible(*inputplane) &&
00320 ixres == xres && iyres == yres &&
00321 inputseq->getImageIndex(t) != -1 &&
00322 isTileAlignedWithInput(0,context, xstart,ystart))
00323 {
00324 return 1;
00325 }
00326 }
00327 }
00328
00329
00330 return 0;
00331 }
00332
00333 void
00334 COP2_MultiInputWipe::passThroughTiles(COP2_Context &context,
00335 const TIL_Plane *plane, int array_index,
00336 float t, int xstart, int ystart,
00337 TIL_TileList *&tiles,
00338 int block, bool *mask, bool *blocked)
00339 {
00340
00341 cop2_MultiInputWipeData *data =
00342 static_cast<cop2_MultiInputWipeData *>(context.data());
00343 bool iblocked = false;
00344
00345
00346 if(data->myPassA)
00347 {
00348 tiles = passInputTile(0,context, plane, array_index, t, xstart,
00349 ystart, block, &iblocked, mask);
00350 }
00351 else if(data->myPassB)
00352 {
00353 tiles = passInputTile(1, context, plane, array_index, t, xstart,
00354 ystart, block, &iblocked, mask);
00355
00356 }
00357
00358
00359
00360 if(!tiles && iblocked && blocked)
00361 *blocked = true;
00362 }
00363
00364 OP_ERROR
00365 COP2_MultiInputWipe::cookMyTile(COP2_Context &context, TIL_TileList *tilelist)
00366 {
00367 cop2_MultiInputWipeData *data =
00368 static_cast<cop2_MultiInputWipeData *>(context.data());
00369 TIL_Region *aregion, *bregion;
00370 int arad, brad;
00371 TIL_Plane fpplane(*context.myPlane);
00372 bool init = false;
00373
00374 arad = data->myBlurRadA;
00375 brad = data->myBlurRadB;
00376
00377
00378 fpplane.setScoped(1);
00379 fpplane.setFormat(TILE_FLOAT32);
00380
00381
00382 if(data->myFaderA != 0.0f)
00383 {
00384 aregion = inputRegion(0, context, &fpplane, 0, context.myTime,
00385 tilelist->myX1 - arad,
00386 tilelist->myY1 - arad,
00387 tilelist->myX2 + arad,
00388 tilelist->myY2 + arad, TIL_HOLD);
00389 if(aregion)
00390 {
00391 boostAndBlur(tilelist, aregion, data->myFaderA,
00392 data->myBoostA, arad, data->myBlurA, false);
00393 init = true;
00394 releaseRegion(aregion);
00395 }
00396 }
00397
00398
00399 if(data->myFaderB != 0.0f)
00400 {
00401 bregion = inputRegion(1, context, &fpplane, 0, context.myTime,
00402 tilelist->myX1 - brad,
00403 tilelist->myY1 - brad,
00404 tilelist->myX2 + brad,
00405 tilelist->myY2 + brad, TIL_HOLD);
00406 if(bregion)
00407 {
00408 boostAndBlur(tilelist, bregion, data->myFaderB,
00409 data->myBoostB, brad, data->myBlurB, init);
00410 init = true;
00411 releaseRegion(bregion);
00412 }
00413 }
00414
00415
00416
00417 if(!init)
00418 tilelist->clearToBlack();
00419
00420 return error();
00421 }
00422
00423 void
00424 COP2_MultiInputWipe::boostAndBlur(TIL_TileList *tiles, TIL_Region *input,
00425 float fade, float boost, int rad, float blur,
00426 bool add)
00427 {
00428 int ti, x,y, i,j, idx;
00429 int w,h;
00430 int stride;
00431 TIL_Tile *itr;
00432 float *src, *scan;
00433 float vedge;
00434 float sum, hsum;
00435 float *dest = NULL;
00436 bool alloced = false;
00437
00438
00439 const float iblur = fade / ((1.0f + blur) * (1.0f + blur));
00440 const float edge = 1.0f - (rad - blur * 0.5f);
00441
00442
00443 w = tiles->myX2 - tiles->myX1 + 1;
00444 h = tiles->myY2 - tiles->myY1 + 1;
00445
00446 stride = w + rad * 2;
00447
00448
00449
00450 if(boost != 0.0f)
00451 {
00452 for(i=0; i<PLANE_MAX_VECTOR_SIZE; i++)
00453 {
00454 src = (float *) input->getImageData(i);
00455 if(src)
00456 for(y=0; y<(h+rad*2) * stride; y++)
00457 *src++ += boost;
00458 }
00459 }
00460
00461
00462
00463
00464
00465 if(!add)
00466 {
00467 dest = new float[w*h];
00468 alloced = true;
00469 }
00470
00471
00472 FOR_EACH_UNCOOKED_TILE(tiles, itr, ti)
00473 {
00474
00475
00476 src = ((float *) input->getImageData(ti)) + rad;
00477
00478 if(add)
00479 {
00480
00481
00482
00483 if(getTileInFP(tiles, dest, ti))
00484 alloced = true;
00485 }
00486 else
00487 {
00488
00489
00490 memset(dest, 0, sizeof(float)*w*h);
00491 }
00492
00493
00494 for(idx=0, y=0; y<h; y++)
00495 {
00496 for(x=0; x<w; x++, idx++)
00497 {
00498 sum = 0.0f;
00499
00500
00501 scan = src+x;
00502 for(i=-rad; i<=rad; i++)
00503 {
00504 vedge = (i == -rad || i == rad) ? edge : 1.0f;
00505
00506 hsum = scan[-rad] * edge;
00507 if(rad)
00508 hsum += scan[rad] * edge;
00509
00510 for(j=-rad+1; j<rad; j++)
00511 hsum += scan[j];
00512
00513 sum += hsum * vedge;
00514 scan += stride;
00515 }
00516
00517
00518
00519 dest[idx] += sum * iblur;
00520 }
00521
00522 src += stride;
00523 }
00524
00525
00526 writeFPtoTile(tiles, dest, ti);
00527 }
00528
00529
00530
00531
00532
00533 if(alloced)
00534 delete [] dest;
00535 }
00536
00537 void
00538 newCop2Operator(OP_OperatorTable *table)
00539 {
00540 table->addOperator(new OP_Operator("hdk_multiwipe",
00541 "HDK Multi Input Wipe",
00542 COP2_MultiInputWipe::myConstructor,
00543 &COP2_MultiInputWipe::myTemplatePair,
00544 2,
00545 2,
00546 &COP2_MultiInputWipe::myVariablePair,
00547 0,
00548 COP2_MultiInputWipe::myInputLabels));
00549 }