Your first OpenMfx plugin#
Plugins may be written in various languages, provided they can interface with the raw C API. The easiest route is to use C++ and the helper SDK provided by the OpenMfx project.
Requirements#
To follow these instructions, you will need the following standard C++ development tools:
A C++ building toolchain (Visual Studio,
gcc
+make
, …)
Important
Make sure that git
and cmake
commands are available in your PATH
.
Building MfxExamples#
In order to get started with writing your first plugin, we will simply modify the MfxExamples project. Let us start by building the project as is:
Clone the MfxExamples repository:
git clone https://github.com/eliemichel/MfxExamples.git
cd MfxExamples
Configure the build:
mkdir build
cd build
cmake ..
Build the project, either by opening the Visual Studio solution generated in the
MfxExamples/build
directory, or by running:
cmake --build .
You should have a mfx_examples.ofx
file created in eiter MfxExamples/build
, MfxExamples/build/Debug
or MfxExamples/build/Release
depending on your configuration.
Adding an effect#
We now add a new effect to the, which we call “MyCoolEffect”.
Create a new file for your effect, called
MyCoolEffect.hpp
.In
plugin.cpp
, include your hpp file and add your effect to the end of theMfxRegister
call:
// [...]
#include "MyCoolEffect.hpp"
// [...]
MfxRegister(
// [...]
BoxGeneratorEffect,
ExplodeEffect,
MyCoolEffect // make sure not to add a comma after the last effect!
)
In
MyCoolEffect.hpp
, we include the Plugin SDK and define a subclass ofMfxEffect
:
#include <OpenMfx/Sdk/Cpp/Plugin/MfxEffect>
class MyCoolEffect : public MfxEffect {
// [...]
}
We define 3 members in the
MyCoolEffect
class:
class MyCoolEffect : public MfxEffect {
public:
// Return the human-readable name of the effect
const char* GetName() override {
return "MyCoolEffect";
}
protected:
// Declare the list of expected input/outputs and parameters of the effect
OfxStatus Describe(OfxMeshEffectHandle) override;
// Compute the output of the effect
OfxStatus Cook(OfxMeshEffectHandle) override;
}
We declare 1 input, 1 output and 1 parameter in
Describe
OfxStatus MyCoolEffect::Describe(OfxMeshEffectHandle) {
AddInput(kOfxMeshMainInput);
AddInput(kOfxMeshMainOutput);
AddParam("translation", double3{0.0, 0.0, 0.0})
.Label("Translation") // Name used for display
.Range(double3{-10.0, -10.0, -10.0}, double3{10.0, 10.0, 10.0});
return kOfxStatOK;
}
Note
The “input” called kOfxMeshMainOutput
is considered as the output. There is at most one output in an effect, and since an output behaves very similarly to an input, one interacts with it using the functions and types in the OpenMfx API.
We implement the core behavior in
Cook
. This code is detailed in the C++ Plugin SDK Guide.
OfxStatus MyCoolEffect::Cook(OfxMeshEffectHandle) {
MfxMesh input_mesh = GetInput(kOfxMeshMainInput).GetMesh();
MfxAttributeProps input_positions;
input_mesh.GetPointAttribute(kOfxMeshAttribPointPosition)
.FetchProperties(input_positions);
double3 translation = GetParam<double3>("translation").GetValue();
MfxMeshProps meshProps;
input_mesh.FetchProperties(meshProps);
MfxMesh output_mesh = GetInput(kOfxMeshMainOutput).GetMesh();
output_mesh.GetCornerAttribute(kOfxMeshAttribCornerPoint)
.ForwardFrom(input_mesh.GetCornerAttribute(kOfxMeshAttribCornerPoint));
if (meshProps.constantFaceSize < 0) {
output_mesh.GetFaceAttribute(kOfxMeshAttribFaceSize)
.ForwardFrom(input_mesh.GetFaceAttribute(kOfxMeshAttribFaceSize));
}
output_mesh.Allocate(meshProps);
MfxAttributeProps output_positions;
output_mesh.GetPointAttribute(kOfxMeshAttribPointPosition)
.FetchProperties(output_positions);
// (NB: This can totally benefit from parallelization using e.g. OpenMP)
for (int i = 0; i < meshProps.pointCount; ++i) {
float* in_p = input_positions.at<float>(i);
float* out_p = output_positions.at<float>(i);
out_p[0] = in_p[0] + static_cast<float>(translation[0]);
out_p[1] = in_p[1] + static_cast<float>(translation[1]);
out_p[2] = in_p[2] + static_cast<float>(translation[2]);
}
output_mesh.Release();
input_mesh.Release();
return kOfxStatOK;
}