latticeNoise/latticeNoiseCmd.cpp

latticeNoise/latticeNoiseCmd.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.
// ==========================================================================
//+
//
// Class: latticeNoiseCmd
//
// Description:
// The latticeNoise command creates a new lattice (ffd) deformer. A
// latticeNoise node is placed between the deformed lattice shape and the
// actual deformer node. This causes the deformed object to wobble over time
// as random continuous noise is applied to the pointes of the lattice.
//
// Once the deformer is created, the regular 'lattice' command can be
// used on it to modify the standard lattice parameters.
//
// One thing to note is that the lattice geometry displayed on the
// screen will not show the added noise. This is done this way
// so that the lattice can be modified with the usual tools without
// the noise node overriding all changes made to the lattice.
//
// Also note that the noise function is reasonably computationally
// expensive, so dense lattices will be slow to update.
//
// eg
// This causes the currently selected object to be deformed
//
// latticeNoise;
//
// This causes the specified geometry to be deformed
//
// latticeNoise sphereShape1;
//
#include <maya/MIOStream.h>
#include "latticeNoise.h"
#include <maya/MObject.h>
#include <maya/MFnLatticeDeformer.h>
#include <maya/MSelectionList.h>
#include <maya/MString.h>
#include <maya/MArgList.h>
#include <maya/MGlobal.h>
#include <maya/MItSelectionList.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnLattice.h>
#include <maya/MDGModifier.h>
#define McheckErr(stat,msg) \
if ( MS::kSuccess != stat ) { \
cerr << msg << endl; \
return MS::kFailure; \
}
void* latticeNoiseCmd::creator()
{
return new latticeNoiseCmd();
}
MStatus latticeNoiseCmd::doIt( const MArgList& args )
{
if ( args.length() > 0 ) {
MString argStr;
unsigned last = args.length();
for ( unsigned i = 0; i < last; i++ ) {
// Get the arg as a string.
//
res = args.get( i, argStr );
McheckErr( res, "Invalid argument type" );
// Attempt to find all of the objects matched
// by the string and add them to the list
//
res = list.add( argStr );
McheckErr( res, "Invalid object" );
}
} else {
// Get the geometry list from what is currently selected in the
// model
//
}
// Create the deformer
//
MObject deformNode = defFn.create( 2, 5, 2, &res );
McheckErr( res, "Deformer creation failed" );
MObject geomObj;
for ( MItSelectionList iter( list, MFn::kGeometric );
!iter.isDone(); iter.next() ) {
// Get the object and add it to the deformation. Note: we just
// ignore objects that we don't understand. This is standard maya
// command behavior
//
iter.getDependNode( geomObj );
defFn.addGeometry( geomObj );
}
// Reset the lattice to bound it's geometry
//
defFn.resetLattice( true );
// Insert the latticeNoise node between the deformed lattice and the
// actual lattice deformer node
//
MFnDependencyNode depNodeFn;
MDGModifier modifier;
MString attrName;
// Make the noise node and get the attributes that we are going to
// connect up
//
MString nodeType("latticeNoise" );
MObject noiseNode = depNodeFn.create( nodeType, &res );
McheckErr( res, "Lattice noise node creation failed" );
attrName.set( "input" );
MObject inputAttr = depNodeFn.attribute( attrName );
attrName.set( "output" );
MObject outputAttr = depNodeFn.attribute( attrName );
attrName.set( "time" );
MObject timeAttr = depNodeFn.attribute( attrName );
// Get the lattice input attribute from the deformer node
//
attrName.set( "deformedLatticePoints" );
MObject destLattAttr = defFn.attribute( attrName );
// Get the lattice shape node so that we can find the output
// attribute
//
MObject deformedLattice = defFn.deformLattice( &res );
McheckErr( res, "Could not get the deformed lattice node" );
MFnLattice latticeShapeFn( deformedLattice, &res );
attrName.set( "latticeOutput" );
MObject sourceLattAttr = latticeShapeFn.attribute( attrName );
// Disconnect lattice from deformer
//
res = modifier.disconnect( deformedLattice, sourceLattAttr,
deformNode, destLattAttr );
McheckErr( res, "Could not disconnect nodes" );
// Insert new noise node
//
modifier.connect( deformedLattice, sourceLattAttr,
noiseNode, inputAttr );
modifier.connect( noiseNode, outputAttr,
deformNode, destLattAttr );
// Find the time node and connect to it
//
list.clear();
list.add( "time1" );
MObject timeNode;
list.getDependNode( 0, timeNode );
MFnDependencyNode timeFn( timeNode, &res );
McheckErr( res, "Could not get the time node" );
attrName.set( "outTime" );
MObject timeOutAttr = timeFn.attribute( attrName );
// Connect to time node
//
modifier.connect( timeNode, timeOutAttr,
noiseNode, timeAttr );
// Perform all of the operations cued up in the modifier
//
res = modifier.doIt();
McheckErr( res, "Error changing deformer graph connections" );
// Lastly, make the new lattice that we have created active
// This is standard Mel command behaviour.
//
MString name = latticeShapeFn.name();
return res;
}