Parametric Parameters

Introduction

Parametric params are new for 1.2 and are optinally supported by host applications. They are specified via the kOfxParamTypeParametric identifier passed into OfxParameterSuiteV1::paramDefine.

These parameters are somewhat more complex than normal parameters and require their own set of functions to manage and manipulate them. The new OfxParametricParameterSuiteV1 is there to do that.

All the defines and suite definitions for parameteric parameters are defined in the file ofxParametricParam.h

Parametric parameters are in effect 'functions' a plug-in can ask a host to arbitrarily evaluate for some value 'x'. A classic use case would be for constructing look-up tables, a plug-in would ask the host to evaluate one at multiple values from 0 to 1 and use that to fill an array.

A host would probably represent this to a user as a cubic curve in a standard curve editor interface, or possibly through scripting. The user would then use this to define the 'shape' of the parameter.

The evaluation of such params is not the same as animation, they are returning values based on some arbitrary argument orthogonal to time, so to evaluate such a param, you need to pass a parametric position and time.

Often, you would want such a parametric parameter to be multi-dimensional, for example, a colour look-up table might want three values, one for red, green and blue. Rather than declare three separate parametric parameters, so a parametric parameter can be multi-dimensional.

Due to the nature of the underlying data, you cannot call certain functions in the ordinary parameter suite when manipulating a parametric parameter. All functions in the standard parameter suite are valid when called on a parametric parameter, with the exception of the following....

  • OfxParameterSuiteV1::paramGetValue
  • OfxParameterSuiteV1::paramGetValueAtTime
  • OfxParameterSuiteV1::paramGetDerivative
  • OfxParameterSuiteV1::paramGetIntegral
  • OfxParameterSuiteV1::paramSetValue
  • OfxParameterSuiteV1::paramSetValueAtTime

Defining Parametric Parameters

Parametric parameters are defined using the standard parameter suite function OfxParameterSuiteV1::paramDefine. The descriptor returned by this call have several non standard parameter properties available. These are
  • kOfxParamPropParametricDimension - the dimension of the parametric parameter,
  • kOfxParamPropParametricUIColour - the colour of the curves of a parametric parameter in any user interface
  • kOfxParamPropParametricInteractBackground - a pointer to an interact entry point, which will be used to draw a background under any user interface,
  • kOfxParamPropParametricRange - the min and max value that the parameter will be evaluated over.

Animating Parametric Parameters

Animation is an optional host feature for parametric parameters. Hosts flag whether they support this feature by setting the host descriptor property kOfxParamHostPropSupportsParametricAnimation.

Getting and Setting Values on a Parametric Parameters

Seeing as we need to pass in the parametric position and dimenstion to evaluate, parametric parameters need a new evaluation mechanism. They do this with the OfxParametricParameterSuiteV1::parametricParamGetValue function. This function returns the value of the parameter at the given time, for the given dimension, adt the given parametric position,.

Parametric parameters are effectively interfaces to some sort of host based curve library. To get/set/delete points in the curve that represents a parameter, the new suite has several functions available to manipulate control points of the underlying curve.

To set the default value of a parametric parameter to anything but the identity, you use the control point setting functions in the new suite to set up a curve on the descriptor returned by OfxParameterSuiteV1::paramDefine. Any instances later created, will have that curve as a default.

Example

This simple example defines a colour lookup table, defines a default, and show how to evaluate the curve

// describe our parameter in 
static OfxStatus
describeInContext( OfxImageEffectHandle  effect,  OfxPropertySetHandle inArgs)
{
  ....
  // define it
  OfxPropertySetHandle props;
  gParamHost->paramDefine(paramSet, kOfxParamTypeParametric, "lookupTable", & props);

  // set standard names and labeles
  gPropHost->propSetString(props, kOfxParamPropHint, 0, "Colour lookup table");
  gPropHost->propSetString(props, kOfxParamPropScriptName, 0, "lookupTable");
  gPropHost->propSetString(props, kOfxPropLabel, 0, "Lookup Table");

  // define it as three dimensional
  gPropHost->propSetInt(props, kOfxParamPropParametricDimension, 0, 3);

  // label our dimensions are r/g/b
  gPropHost->propSetString(props, kOfxParamPropDimensionLabel, 0, "red");
  gPropHost->propSetString(props, kOfxParamPropDimensionLabel, 1, "green");
  gPropHost->propSetString(props, kOfxParamPropDimensionLabel, 2, "blue");

  // set the UI colour for each dimension
  for(int component = 0; component < 3; ++component) {
     gPropHost->propSetDouble(props, kOfxParamPropParametricUIColour, component * 3 + 0, component % 3 == 0 ? 1 : 0);
     gPropHost->propSetDouble(props, kOfxParamPropParametricUIColour, component * 3 + 1, component % 3 == 1 ? 1 : 0);
     gPropHost->propSetDouble(props, kOfxParamPropParametricUIColour, component * 3 + 2, component % 3 == 2 ? 1 : 0);
  }

  // set the min/max parametric range to 0..1
  gPropHost->propSetDouble(props, kOfxParamPropParametricRange, 0, 0.0);
  gPropHost->propSetDouble(props, kOfxParamPropParametricRange, 1, 1.0);
 
  // set a default curve, this example sets an invert 
  OfxParamHandle descriptor;
  gParamHost->paramGetHandle(paramSet, "lookupTable", &descriptor, NULL);
  for(int component = 0; component < 3; ++component) {
    // add a control point at 0, value is 1
    gParametricParamHost->parametricParamAddControlPoint(descriptor,
                                                          component, // curve to set 
                                                          0.0,   // time, ignored in this case, as we are not adding a ket
                                                          0.0,   // parametric position, zero
                                                          1.0,   // value to be, 1
                                                          false);   // don't add a key
    // add a control point at 1, value is 0
    gParametricParamHost->parametricParamAddControlPoint(descriptor, component, 0.0, 1.0, 0.0, false);
  }
 
  ...
}

void render8Bits(double currentFrame, otherStuff...)
{
   ...

   // make three luts from our curves   
   unsigned char lut[3][256];

  OfxParamHandle param;
  gParamHost->paramGetHandle(paramSet, "lookupTable", &param, NULL);
  for(int component = 0; component < 3; ++component) {
    for(int position = 0; position < 256; ++position) {
      // position to evaluate the param at
      float parametricPos = float(position)/255.0f;
       
      // evaluate the parametric param
      float value;
      gParametricParamHost->parametricParamGetValue(param, component, currentFrame, parametricPos, &value);
      value = value * 255;
      value = clamp(value, 0, 255);

      // set that in the lut
      lut[dimension][position] = (unsigned char)value;
    }
  }
  ...
}