simpleLoftNode/simpleLoftNode.cpp
 
 
 
simpleLoftNode/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;
}