- Main Page
- Related Pages
- Modules
- Classes
- Examples

# simpleLoftNode.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk
    // license agreement provided at the time of installation or download,
    // or which otherwise accompanies this software in either electronic
    // or hard copy form.
    // ==========================================================================
    //+

    #include <string.h>
    #include <maya/MIOStream.h>
    #include <math.h>

    #include <maya/MPxNode.h>
    #include <maya/MPxCommand.h>

    #include <maya/MFnNumericAttribute.h>
    #include <maya/MFnTypedAttribute.h>
    #include <maya/MFnPlugin.h>

    #include <maya/MFnNurbsCurve.h>
    #include <maya/MFnNurbsSurface.h>
    #include <maya/MFnNurbsCurveData.h>
    #include <maya/MFnNurbsSurfaceData.h>

    #include <maya/MPointArray.h>
    #include <maya/MDoubleArray.h>

    #include <maya/MString.h>
    #include <maya/MTypeId.h>
    #include <maya/MPlug.h>
    #include <maya/MDataBlock.h>
    #include <maya/MDataHandle.h>

    #include <maya/MGlobal.h>
    #include <maya/MItCurveCV.h>
    #include <maya/MDagPath.h>

    class simpleLoft : public MPxNode
    {
    public:
                            simpleLoft() {};
        virtual             ~simpleLoft();

        virtual MStatus     compute( const MPlug& plug, MDataBlock& data );
        MObject             loft( MObject &curve, MObject &surfFn, MStatus &stat );

        static  void*       creator();
        static  MStatus     initialize();

    public:
        static  MObject     inputCurve;     // The input curve.
        static  MObject     outputSurface;  // The output curve.
        static  MTypeId     id;             // The IFF type id
    };

    MTypeId     simpleLoft::id( 0x80011 );
    MObject     simpleLoft::inputCurve;
    MObject     simpleLoft::outputSurface;

    simpleLoft::~simpleLoft() {}

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

    MStatus simpleLoft::initialize()
    {
        MFnTypedAttribute   typedAttr;
        MStatus             stat;

        inputCurve = typedAttr.create( "inputCurve", "in",
                     MFnNurbsCurveData::kNurbsCurve, &stat );

        if ( !stat ) {
            stat.perror("ERROR creating simpleLoft curve attribute");
            return stat;
        }

        outputSurface = typedAttr.create( "outputSurface", "out",
                    MFnNurbsSurfaceData::kNurbsSurface, &stat );

        if ( !stat ) {
            stat.perror("ERROR creating simpleLoft surface attribute");
            return stat;
        }
        typedAttr.setStorable( false );

        stat = addAttribute( inputCurve );
            if (!stat) { stat.perror("addAttribute"); return stat;}
        stat = addAttribute( outputSurface );
            if (!stat) { stat.perror("addAttribute"); return stat;}

        stat = attributeAffects( inputCurve, outputSurface );
            if (!stat) { stat.perror("attributeAffects"); return stat;}

        return MS::kSuccess;
    }

    MObject simpleLoft::loft( MObject &curve, MObject &newSurfData, MStatus &stat )
    {
        MFnNurbsSurface surfFn;

        MPointArray cvs;
        MDoubleArray ku, kv;
        MFnNurbsCurve curveFn (curve);

        stat = curveFn.getCVs (cvs, MSpace::kWorld);
        if ( stat != MS::kSuccess )
        {
            cerr << "Error in getting CVs: " << stat << endl;
            return MObject::kNullObj;
        }

        int i, j, k = cvs.length();

        // create knot vectors for U and V

        ku.append( 0.0 );
        ku.append( 0.0 );
        ku.append( 0.0 );

        ku.append( 1.0 );
        ku.append( 1.0 );
        ku.append( 1.0 );

        kv.append( 0.0 );
        kv.append( 0.0 );
        kv.append( 0.0 );

        for ( i = 1; i < k-3; i ++ )
            kv.append( (double) i );

        kv.append( k-3 );
        kv.append( k-3 );
        kv.append( k-3 );

        // create cvs for the surface

        for ( i = 1; i < 4; i++ )
        {
            for ( j = 0; j < k; j++ )
            {
                MPoint point = cvs[j];
                point.z += (double) i;  // loft in Z by 1
                cvs.append( point );
            }
        }

        MObject surf = surfFn.create(
            cvs, ku, kv, 3, 3,
            MFnNurbsSurface::kOpen, MFnNurbsSurface::kOpen,
            false, newSurfData, &stat );

        if ( stat != MS::kSuccess )
        {
            cerr << "Error in creating surface: " << stat << endl;
            return MObject::kNullObj;
        }

        // stat = MGlobal::addToModel( surf );
        return surf;

    }

    MStatus simpleLoft::compute( const MPlug& plug, MDataBlock& data )
    {
        MStatus stat;

        if ( plug == outputSurface )    // loft inputCurve into surface
        {
            MDataHandle inputData = data.inputValue( inputCurve, &stat );
            if( stat != MS::kSuccess )
            {
                cerr << "ERROR getting data: " << stat << endl;
                return stat;
            }

            MObject curve = inputData.asNurbsCurve();
            MFnNurbsCurve curveFn( curve, &stat );
            if( stat != MS::kSuccess )
            {
              cerr << "ERROR creating curve function set:" << stat << endl;
              return stat;
            }

            MDataHandle surfHandle = data.outputValue( simpleLoft::outputSurface );
            if( stat != MS::kSuccess )
            {
              cerr << "Error in getting data handle: " << stat << endl;
              return stat;
            }

            MFnNurbsSurfaceData dataCreator;
            MObject newSurfData = dataCreator.create( &stat );
            if ( stat != MS::kSuccess ) {
              cerr << "Error creating new nurbs surface data block: "
                   << stat << endl;
              return stat;
            }

            /* MObject newSurf = */ loft( curve, newSurfData,  stat );
            if( stat != MS::kSuccess )
            {
              cerr << "Error in creating surface: " << stat << endl;
              return stat;
            }

            // newSurf is the new surface object, but it has been packed
            // into the datablock we created for it, and the data block
            // is what we must put onto the plug.
            surfHandle.set( newSurfData );

            stat = data.setClean( plug );
            if( stat != MS::kSuccess )
            {
              cerr << "Error in cleaning outputSurface plug: "
                   << stat << endl;
              return stat;
            }
        }
        else
        {
            return MS::kUnknownParameter;
        }

        return MS::kSuccess;
    }

    MStatus initializePlugin( MObject obj )
    {
        MStatus   status;
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");

        status = plugin.registerNode( "simpleLoft", simpleLoft::id,
                                      simpleLoft::creator, simpleLoft::initialize );
        if (!status) {
            status.perror("registerNode");
            return status;
        }

        return status;
    }

    MStatus uninitializePlugin( MObject obj)
    {
        MStatus   status;
        MFnPlugin plugin( obj );

        status = plugin.deregisterNode( simpleLoft::id );
        if (!status) {
            status.perror("deregisterNode");
            return status;
        }

        return status;
    }