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 #include <UT/UT_DSOVersion.h>
00029 #include <OP/OP_OperatorTable.h>
00030
00031 #include <CH/CH_LocalVariable.h>
00032 #include <CHOP/CHOP_VariableList.h>
00033 #include <PRM/PRM_Include.h>
00034
00035 #include <UT/UT_Interrupt.h>
00036
00037 #include "CHOP_Blend.h"
00038
00039 using namespace HDK_Sample;
00040
00041 CHOP_SWITCHER(2,"Blend");
00042
00043 static PRM_Name methodItems[] = {
00044 PRM_Name("prop", "Proportional"),
00045 PRM_Name("dif", "Difference"),
00046 PRM_Name(0),
00047 };
00048
00049 static PRM_ChoiceList methodMenu((PRM_ChoiceListType)
00050 (PRM_CHOICELIST_EXCLUSIVE |
00051 PRM_CHOICELIST_REPLACE),
00052 methodItems);
00053
00054 static PRM_Name names[] = {
00055 PRM_Name("method", "Method"),
00056 PRM_Name("firstweight", "Omit First Weight Channel"),
00057 };
00058
00059 PRM_Template
00060 CHOP_Blend::myTemplateList[] =
00061 {
00062 PRM_Template(PRM_SWITCHER, 2, &PRMswitcherName, switcher),
00063 PRM_Template(PRM_ORD, 1, &names[0], PRMoneDefaults,&methodMenu),
00064 PRM_Template(PRM_TOGGLE, 1, &names[1], PRMzeroDefaults),
00065
00066 PRM_Template(),
00067 };
00068 OP_TemplatePair CHOP_Blend::myTemplatePair(
00069 CHOP_Blend::myTemplateList, &CHOP_Node::myTemplatePair);
00070
00071 unsigned
00072 CHOP_Blend::disableParms()
00073 {
00074 unsigned changes = CHOP_Node::disableParms();
00075
00076
00077 changes += enableParm("firstweight", GETDIFFERENCE());
00078
00079 return changes;
00080 }
00081
00082
00083
00084 CH_LocalVariable
00085 CHOP_Blend::myVariableList[] = {
00086 { 0, 0, 0 }
00087 };
00088 OP_VariablePair CHOP_Blend::myVariablePair(
00089 CHOP_Blend::myVariableList, &CHOP_Node::myVariablePair);
00090
00091
00092 OP_Node *
00093 CHOP_Blend::myConstructor(OP_Network *net,
00094 const char *name,
00095 OP_Operator *op)
00096 {
00097 return new CHOP_Blend(net, name, op);
00098 }
00099
00100
00101
00102
00103 CHOP_Blend::CHOP_Blend( OP_Network *net,
00104 const char *name,
00105 OP_Operator *op)
00106 : CHOP_Node(net, name, op)
00107 {
00108 myParmBase = getParmList()->getParmIndex( names[0].getToken() );
00109 }
00110
00111 CHOP_Blend::~CHOP_Blend()
00112 {
00113 }
00114
00115 const CL_Clip *
00116 CHOP_Blend::getCacheInputClip(int j)
00117 {
00118
00119
00120 return (j>=0 && j<myInputClip.entries()) ?
00121 myInputClip(j) : 0;
00122 }
00123
00124 OP_ERROR
00125 CHOP_Blend::cookMyChop(OP_Context &context)
00126 {
00127 const CL_Clip *blendclip;
00128 const CL_Clip *clip;
00129 const CL_Track *track, *blend;
00130 int num_motion_tracks;
00131 int num_clips;
00132 float weight, *data, *total;
00133 int i,j,k,samples;
00134 float time;
00135 float val;
00136 int difference;
00137 int fweight;
00138 UT_Interrupt *boss = UTgetInterrupt();
00139 short int percent = -1;
00140 int stopped = 0;
00141 float adjust[2] = {1.0f, -1.0f};
00142 const float *src, *w;
00143
00144 difference = GETDIFFERENCE();
00145 if(difference)
00146 fweight = FIRST_WEIGHT();
00147 else
00148 fweight = 0;
00149
00150
00151
00152 blendclip = copyInputAttributes(context);
00153 if(!blendclip)
00154 return error();
00155
00156
00157
00158 num_clips = findInputClips(context, blendclip);
00159
00160
00161 num_motion_tracks = findFirstAvailableTracks(context);
00162
00163 samples = myClip->getTrackLength();
00164
00165
00166
00167 myTotalArray.resize(samples);
00168 myTotalArray.entries(samples);
00169 total = myTotalArray.array();
00170
00171 if(boss->opStart("Blending Channels"))
00172 {
00173 for(i=0; i<num_motion_tracks; i++)
00174 {
00175
00176
00177
00178
00179 myClip->getTrack(i)->constant(0);
00180 data = myClip->getTrack(i)->getData();
00181
00182
00183 myTotalArray.constant(difference ? 1.0f : 0.0f);
00184
00185
00186
00187
00188 for(j=difference?1:0; j<num_clips; j++)
00189 {
00190 clip = getCacheInputClip(j+1);
00191 if(!clip)
00192 continue;
00193
00194
00195
00196 if(difference && fweight)
00197 blend = blendclip->getTrack(j-1);
00198 else
00199 blend = blendclip->getTrack(j);
00200 track = clip->getTrack(i);
00201
00202 if(!track || !blend)
00203 continue;
00204
00205
00206
00207 w = blend->getData();
00208
00209
00210
00211 if (myClip->isSameRange(*clip))
00212 {
00213 src = track->getData();
00214 for(k=0; k<samples; k++)
00215 {
00216 if (w[k])
00217 {
00218
00219 data[k] += w[k]*src[k];
00220
00221
00222
00223 total[k] += w[k]*adjust[difference];
00224 }
00225 }
00226 }
00227 else
00228 {
00229
00230
00231 for(k=0; k<samples; k++)
00232 {
00233 time = myClip->getTime(k + myClip->getStart());
00234 if (w[k])
00235 {
00236 data[k] += w[k] *
00237 clip->evaluateSingleTime(track, time);
00238 total[k] += w[k]*adjust[difference];
00239 }
00240 }
00241 }
00242
00243
00244 if(boss->opInterrupt())
00245 {
00246 stopped = 1;
00247 break;
00248 }
00249 }
00250
00251
00252 if(!stopped)
00253 {
00254 if(!difference)
00255 {
00256
00257
00258 j = myAvailableTracks(i);
00259 if ( j!=-1 && getCacheInputClip(j))
00260 {
00261 track = getCacheInputClip(j)->getTrack(i);
00262 blend = blendclip->getTrack(j);
00263 if(blend)
00264 w = blend->getData();
00265 else
00266 continue;
00267 }
00268 else
00269 track = 0;
00270
00271 for(k=0; k<samples; k++)
00272 {
00273 if(!UTequalZero(total[k], 0.001F))
00274 {
00275
00276 data[k] /= total[k];
00277 }
00278 else
00279 {
00280
00281
00282 if(track && blend)
00283 {
00284 time = myClip->getTime(k + myClip->getStart());
00285 val = clip->evaluateSingleTime(track,time);
00286
00287 data[k] -= w[k]*val;
00288 total[k]-= w[k];
00289
00290 weight = 1.0F - total[k];
00291 total[k]+= weight;
00292 data[k] += weight*val;
00293
00294 data[k] /= total[k];
00295 }
00296 }
00297 }
00298 }
00299 else
00300 {
00301
00302
00303
00304 j = myAvailableTracks(i);
00305 if (j != -1)
00306 {
00307 clip = getCacheInputClip(j);
00308 track = clip ? clip->getTrack(i) : 0;
00309
00310 if (track)
00311 {
00312 if (myClip->isSameRange(*clip))
00313 {
00314 const float *src = track->getData();
00315 for(k=0; k<samples; k++)
00316 data[k] += src[k] * total[k];
00317 }
00318 else
00319 {
00320 for(k=0; k<samples; k++)
00321 {
00322 time= myClip->getTime(k+myClip->getStart());
00323 val = clip->evaluateSingleTime(track, time);
00324 data[k] += val * total[k];
00325 }
00326 }
00327 }
00328 }
00329 if(boss->opInterrupt(percent))
00330 {
00331 stopped = 1;
00332 break;
00333 }
00334
00335 }
00336 }
00337 if(stopped)
00338 break;
00339 }
00340 }
00341 boss->opEnd();
00342
00343 return error();
00344 }
00345
00346 int
00347 CHOP_Blend::findInputClips(OP_Context &context, const CL_Clip *blendclip)
00348 {
00349 int i, num_clips;
00350
00351
00352 num_clips = blendclip->getNumTracks();
00353
00354
00355
00356 if(GETDIFFERENCE() && FIRST_WEIGHT())
00357 num_clips ++;
00358
00359
00360 if (num_clips >= nInputs())
00361 num_clips = nInputs()-1;
00362
00363
00364 myInputClip.resize(num_clips+1);
00365 myInputClip.entries(num_clips+1);
00366
00367 for (i=0; i<=num_clips; i++)
00368 myInputClip(i) = inputClip(i, context);
00369
00370 return num_clips;
00371 }
00372
00373
00374
00375 int
00376 CHOP_Blend::findFirstAvailableTracks(OP_Context &context)
00377 {
00378 const CL_Track *track;
00379 const CL_Clip *clip;
00380 int i, j;
00381 int num_motion_tracks;
00382
00383
00384
00385 num_motion_tracks = 0;
00386 for(i=1; i<nInputs(); i++)
00387 {
00388 clip = inputClip(i, context);
00389
00390 if(!clip)
00391 continue;
00392
00393 if(clip->getNumTracks() > num_motion_tracks)
00394 num_motion_tracks = clip->getNumTracks();
00395 }
00396
00397
00398
00399
00400
00401 myAvailableTracks.resize(num_motion_tracks);
00402 myAvailableTracks.entries(num_motion_tracks);
00403
00404 for(i=0; i<num_motion_tracks; i++)
00405 {
00406 track = 0;
00407 j = 1;
00408
00409 while( !track && j<nInputs())
00410 {
00411 clip = inputClip(j, context);
00412 if(!clip)
00413 {
00414 j++;
00415 continue;
00416 }
00417
00418 track = clip->getTrack(i);
00419 if(!track)
00420 j++;
00421 }
00422
00423 myAvailableTracks(i) = track ? j: -1;
00424 }
00425
00426
00427
00428 for(i=0; i<num_motion_tracks; i++)
00429 {
00430 j = myAvailableTracks(i);
00431
00432 if (j == -1)
00433 continue;
00434
00435 track = inputClip(j, context)->getTrack(i);
00436 if (track)
00437 myClip->dupTrackInfo(track);
00438 }
00439
00440
00441 return num_motion_tracks;
00442 }
00443
00444
00445 void newChopOperator(OP_OperatorTable *table)
00446 {
00447 table->addOperator(new OP_Operator("hdk_blend",
00448 "HDK Blend",
00449 CHOP_Blend::myConstructor,
00450 &CHOP_Blend::myTemplatePair,
00451 2,
00452 9999,
00453 &CHOP_Blend::myVariablePair));
00454 }