InterpNode コード サンプルの概説

シェーディング ノード プラグインは、複合アトリビュート(Compound Attributes)単純なアトリビュート(Simple Attributes)の使用に依存します。レンダリング サンプラとシェーディング ネットワーク間のデータ マッピングは、アトリビュート名で行います。この方法は直接的で習得しやすく、十分に一般的で、現在のレンダリング要件と将来の拡張に対処できます。

プラグインが必要とするすべてのレンダリング アトリビュートは、現在のサンプリングの前に計算されています。プラグインの compute() メソッドに渡される「datablock」引数には、ノードが要求するレンダリング アトリビュート情報が含まれています。ディペンデンシー グラフによってプラグインが評価されると、評価する特定アトリビュートの「plug」引数も渡されます。評価を最適化するには、プラグイン内で定義した出力アトリビュートのみをチェックします。

このプラグイン ノードの例には、id アトリビュート以外に 20 個のアトリビュートが含まれています。

このノードは、データ ブロックから取得したサーフェス法線の方向に基づいて 2 つのカラー間を補間し、そのクラスの compute() メソッドを使用して、出力カラー アトリビュートに配置するカラーを派生させます。

派生

class InterpNode : public MPxNode 
{
public:
    InterpNode();
    virtual ~InterpNode();
    virtual MStatus compute( const MPlug&, MDataBlock& );
    static void * creator();
    static MStatus initialize();
    static MTypeId id;
protected:
    static MObject InputValue;
    static MObject color1R,color1G,color1B,color1;
    static MObject color2R,color2G,color2B,color2;
    static MObject aNormalCameraX, aNormalCameraY,
    aNormalCameraZ, aNormalCamera;
    static MObject aPointCameraX, aPointCameraY,
    aPointCameraZ, aPointCamera;
    static MObject aOutColorR, aOutColorG, aOutColorB,
    aOutColor;
};
MObject InterpNode::InputValue;
MObject InterpNode::color1R;
MObject InterpNode::color1G;
MObject InterpNode::color1B;
MObject InterpNode::color1;
MObject InterpNode::color2R;
MObject InterpNode::color2G;
MObject InterpNode::color2B;
MObject InterpNode::color2;
MObject InterpNode::aNormalCameraX;
MObject InterpNode::aNormalCameraY;
MObject InterpNode::aNormalCameraZ;
MObject InterpNode::aNormalCamera;
MObject InterpNode::aPointCameraX;
MObject InterpNode::aPointCameraY;
MObject InterpNode::aPointCameraZ;
MObject InterpNode::aPointCamera;
MObject InterpNode::aOutColorR;
MObject InterpNode::aOutColorG;
MObject InterpNode::aOutColorB;
MObject InterpNode::aOutColor;

コンストラクタ/デストラクタ

InterpNode::InterpNode() { }
InterpNode::~InterpNode() { }

クリエータ

void* InterpNode::creator()
{
    return new InterpNode();
}

initializePlugin/uninitializePlugin

MStatus initializePlugin( MObject obj )
{
    const MString UserClassify( "utility/general" );
    MFnPlugin plugin( obj, "Autodesk", "1.0",
    "Any");
    plugin.registerNode( "Interp", InterpNode::id,
    InterpNode::creator,
    InterpNode::initialize,
    MPxNode::kDependNode, &UserClassify);
    return MS::kSuccess;
}

MStatus uninitializePlugin( MObject obj)
{
    MFnPlugin plugin( obj );
    plugin.deregisterNode( InterpNode::id );
    return MS::kSuccess;
}

初期化

MStatus InterpNode::initialize()
{
    MFnNumericAttribute nAttr; 
    // Inputs and Attributes
    //
    // User defined attributes require a long-name and short-
    // name that are required to be unique within the node.
    // (See the compound attribute color1 named "Sides".)
    //
    // Rendering attributes that your node wants to get from
    // the sampler require them to be defined given the pre-
    // defined unique long-name.(See the compound attribute
    // aNormalCamera named "normalCamera".)
    // 
    // User defined Attributes are generally something that you 
    // want to store in the Maya file. The setStorable(true)
    // method enables an attribute to be stored into the Maya
    // scene file. 
    //
    // Rendering attributes are primarily data that is
    // generated per sample and not something that you want to
    // store in a file. To disable an attribute from being
    // recorded to the Maya scene file use the
    // setStorable(false) method.
    //
    // Simple attributes that represent a range of values can
    // enable a slider on the Attribute Editor by using the
    // methods setMin() and setMax(). 
    // (See the simple attribute InputValue named "Power".)
    //
    // Compound attributes that represent a vector of 3 floats
    // can enable a color swatch on the Attribute Editor that
    // will launch a color picker tool by using the method
    // setUsedAsColor(true).
    // (See the compound attribute color1 name "Sides".)
    //
    // Both Simple and Compound attributes can be initialized
    // with a default value using the method setDefault().
    //
    // Attributes by default show up in the Attribute Editor
    // and in the Connection Editor unless they are specified
    // as being hidden by using the method setHidden(true). 
    //
    // Attributes by default have both read/write access in the
    // dependency graph. To change an attributes behaviour you
    // can use the methods setReadable() and setWritable(). The
    // method setReadable(true) indicates that the attribute
    // can be used as the source in a dependency graph
    // connection. The method setWritable(true) indicates that
    // the attribute can be used as the destination in a
    // dependency graph connection.
    // (See the compound attribute aOutColor named "outColor"
    // below. It has been marked as a read-only attribute since
    // it is the computed result of the node, it is not stored
    // in the Maya file since it is always computed, and it is
    // marked as hidden to prevent it from being displayed in
    // the user interface.)
    // 
    //
    // User defined input value
    InputValue = nAttr.create( "Power", "pow",
    MFnNumericData::kFloat);
    nAttr.setDefault(1.0f);
    nAttr.setMin(0.0f);
    nAttr.setMax(3.0f);
    nAttr.setStorable(true);
    // User defined color attribute
    color1R = nAttr.create( "color1R", "c1r",
    MFnNumericData::kFloat);
    color1G = nAttr.create( "color1G", "c1g",
    MFnNumericData::kFloat);
    color1B = nAttr.create( "color1B", "c1b",
    MFnNumericData::kFloat);
    color1 = nAttr.create( "Sides", "c1", color1R, color1G,
    color1B);
    nAttr.setStorable(true);
    nAttr.setUsedAsColor(true);
    nAttr.setDefault(1.0f, 1.0f, 1.0f);
    color2R = nAttr.create( "color2R", "c2r",
    MFnNumericData::kFloat);
    color2G = nAttr.create( "color2G", "c2g",
    MFnNumericData::kFloat);
    color2B = nAttr.create( "color2B", "c2b",
    MFnNumericData::kFloat);
    color2 = nAttr.create( "Facing", "c2", color2R,
    color2G, color2B);
    nAttr.setStorable(true);
    nAttr.setUsedAsColor(true);
    nAttr.setDefault(0.0f, 0.0f, 0.0f);
    // Surface Normal supplied by the render sampler
    aNormalCameraX = nAttr.create( "normalCameraX", "nx",
    MFnNumericData::kFloat);
    nAttr.setStorable(false);
    nAttr.setDefault(1.0f);
    aNormalCameraY = nAttr.create( "normalCameraY", "ny",
    MFnNumericData::kFloat);
    nAttr.setStorable(false);
    nAttr.setDefault(1.0f);
    aNormalCameraZ = nAttr.create( "normalCameraZ", "nz",
    MFnNumericData::kFloat);
    nAttr.setStorable(false);
    nAttr.setDefault(1.0f);
    aNormalCamera = nAttr.create( "normalCamera","n",
    aNormalCameraX, 
    aNormalCameraY, aNormalCameraZ);
    nAttr.setStorable(false);
    nAttr.setHidden(true);
    // Point on surface in camera space, will be used to compute view vector
    aPointCameraX = nAttr.create( "pointCameraX", "px",
    MFnNumericData::kFloat);
    nAttr.setStorable(false);
    nAttr.setDefault(1.0f);
    aPointCameraY = nAttr.create( "pointCameraY", "py",
    MFnNumericData::kFloat);
    nAttr.setStorable(false);
    nAttr.setDefault(1.0f);
    aPointCameraZ = nAttr.create( "pointCameraZ", "pz",
    MFnNumericData::kFloat);
    nAttr.setStorable(false);
    nAttr.setDefault(1.0f);
    aPointCamera = nAttr.create( "pointCamera","p",
    aPointCameraX, 
    aPointCameraY, aPointCameraZ);
    nAttr.setStorable(false);
    nAttr.setHidden(true);
    // Outputs
    aOutColorR = nAttr.create( "outColorR", "ocr",
    MFnNumericData::kFloat);
    aOutColorG = nAttr.create( "outColorG", "ocg",
    MFnNumericData::kFloat);
    aOutColorB = nAttr.create( "outColorB", "ocb",
    MFnNumericData::kFloat);
    aOutColor = nAttr.create( "outColor", "oc",
    aOutColorR, aOutColorG, aOutColorB);
    nAttr.setStorable(false);
    nAttr.setHidden(false);
    nAttr.setReadable(true);
    nAttr.setWritable(false);
    addAttribute(InputValue);
    addAttribute(color1R);
    addAttribute(color1G);
    addAttribute(color1B);
    addAttribute(color1);
    addAttribute(color2R);
    addAttribute(color2G);
    addAttribute(color2B);
    addAttribute(color2);
    addAttribute(aNormalCameraX);
    addAttribute(aNormalCameraY);
    addAttribute(aNormalCameraZ);
    addAttribute(aNormalCamera);
    addAttribute(aPointCameraX);
    addAttribute(aPointCameraY);
    addAttribute(aPointCameraZ);
    addAttribute(aPointCamera);
    addAttribute(aOutColorR);
    addAttribute(aOutColorG);
    addAttribute(aOutColorB);
    addAttribute(aOutColor);
    attributeAffects (InputValue, aOutColor);
    attributeAffects (color1R, color1);
    attributeAffects (color1G, color1);
    attributeAffects (color1B, color1);
    attributeAffects (color1, aOutColor);
    attributeAffects (color2R, color2);
    attributeAffects (color2G, color2);
    attributeAffects (color2B, color2);
    attributeAffects (color2, aOutColor);
    attributeAffects (aNormalCameraX, aOutColor);
    attributeAffects (aNormalCameraY, aOutColor);
    attributeAffects (aNormalCameraZ, aOutColor);
    attributeAffects (aNormalCamera, aOutColor);
    attributeAffects (aPointCameraX, aOutColor);
    attributeAffects (aPointCameraY, aOutColor);
    attributeAffects (aPointCameraZ, aOutColor);
    attributeAffects (aPointCamera, aOutColor);
    return MS::kSuccess;
}

ID 文字列

MTypeId InterpNode::id( 0x81005 );

compute メソッド

MStatus InterpNode::compute( const MPlug& plug, MDataBlock& block )
{
    int k=0;
    float gamma,scalar;
    k |= (plug == aOutColor);
    k |= (plug == aOutColorR);
    k |= (plug == aOutColorG);
    k |= (plug == aOutColorB);
    if (!k) return MS::kUnknownParameter;
    MFloatVector resultColor(0.0,0.0,0.0);
    MFloatVector& Side = block.inputValue( color1 ).
    asFloatVector();
    MFloatVector& Face = block.inputValue( color2 ).
    asFloatVector();
    MFloatVector& surfaceNormal = block.
    inputValue( aNormalCamera ).
    asFloatVector();
    MFloatVector& viewVector = block.
    inputValue( aPointCamera ).
    asFloatVector();
    float power = block.inputValue( InputValue ).asFloat();
    // Normalize the view vector
    double d = sqrt((viewVector[0] * viewVector[0]) +
    (viewVector[1] * viewVector[1]) +
    (viewVector[2] * viewVector[2]));
    if (d != (double)0.0) {
        viewVector[0] /= d;
        viewVector[1] /= d;
        viewVector[2] /= d;
    }
 
    // find dot product
    float scalarNormal = ((viewVector[0]*surfaceNormal[0])
                       + (viewVector[1]*surfaceNormal[1])
                       + (viewVector[2]*surfaceNormal[2]));
    // take the absolute value
    if (scalarNormal < 0.0) scalarNormal *= -1.0;
    // Use InputValue to change interpolation
    // power == 1.0 linear
    // power >= 0.0 use gamma function
    //
    if (power > 0.0) {
        gamma = 1.0 / power;
        scalar = pow(scalarNormal,gamma);
    }
    else { scalar = 0.0; }
    // Interpolate the colors
    MFloatVector interp(0.0,0.0,0.0);
    interp[0] = scalar * (Face[0] - Side[0]);
    interp[1] = scalar * (Face[1] - Side[1]);
    interp[2] = scalar * (Face[2] - Side[2]);
    resultColor[0] = Side[0] + interp[0];
    resultColor[1] = Side[1] + interp[1];
    resultColor[2] = Side[2] + interp[2];
    // set ouput color attribute
    MDataHandle outColorHandle = block.
    outputValue( aOutColor );
    MFloatVector& outColor = outColorHandle.
    asFloatVector();
    outColor = resultColor;
    outColorHandle.setClean();
    return MS::kSuccess;
}

InterpNode サンプルのアトリビュート エディタ(Attribute Editor) ビュー

InterpNode 接続の接続エディタ(Connection Editor) ビュー

InterpNode 接続のハイパーグラフ(Hypergraph) ビュー