latticeNoise/latticeNoiseNode.cpp

latticeNoise/latticeNoiseNode.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: latticeNoiseNode
//
// Description:
// A "latticeNoise" node adds random noise to lattice geometry over time.
// This makes the geometry being deformed by the lattice look like
// wobbly jello.
//
//
// Node: latticeNoise
//
// Attributes: input - input lattice
// amplitude - amplitude of the noise
// frequency - frequency of the noise
// time - the current time
// output - the modified lattice
//
#include "latticeNoise.h"
#include <string.h>
#include <maya/MIOStream.h>
#include <stdio.h>
#include <math.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnLattice.h>
#include <maya/MFnLatticeData.h>
#include <maya/MString.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MTime.h>
// CONSTANTS
//
#define DEF_AMPLITUDE 0.2
#define DEF_FREQ 4.0
#define McheckErr(stat,msg) \
if ( MS::kSuccess != stat ) { \
cerr << msg; \
return MS::kFailure; \
}
// latticeNoiseNode Methods //
MTypeId latticeNoiseNode::id( 0x80010 );
MObject latticeNoiseNode::input;
MObject latticeNoiseNode::amplitude;
MObject latticeNoiseNode::frequency;
MObject latticeNoiseNode::time;
MObject latticeNoiseNode::output;
MStatus latticeNoiseNode::compute( const MPlug& plug, MDataBlock& data )
{
MStatus returnStatus;
float noiseAmplitude;
float noiseFreq;
if( plug == output )
{
// Get the lattice data from the input attribute. First get the
// data object, and then use the lattice data function set to extract
// the actual lattice.
//
// Get the data handle
//
MDataHandle inputData = data.inputValue( input, &returnStatus );
McheckErr( returnStatus, "ERROR getting lattice data handle\n" );
// Get the data object
//
MObject latticeData = inputData.data();
MFnLatticeData dataFn( latticeData );
// Get the actual geometry
//
MObject lattice = dataFn.lattice();
MFnLattice lattFn( lattice, &returnStatus );
McheckErr( returnStatus, "ERROR getting lattice geometry\n" );
// Do the same for the output lattice
//
MDataHandle outputData = data.outputValue( output, &returnStatus );
McheckErr( returnStatus, "ERROR getting lattice data handle\n" );
// Get the data object
//
latticeData = outputData.data();
if ( latticeData.isNull() ) {
// The data object for this attribute has not been created yet, so
// we'll create it
//
latticeData = dataFn.create();
} else {
// Use the data object that is already there
//
dataFn.setObject( latticeData );
}
// Get the actual geometry
//
MObject outLattice = dataFn.lattice();
MFnLattice outLattFn( outLattice, &returnStatus );
McheckErr( returnStatus, "ERROR getting lattice geometry\n" );
// Get the amplitude and frequency
//
MDataHandle ampData = data.inputValue( amplitude, &returnStatus );
McheckErr( returnStatus, "ERROR getting amplitude\n" );
noiseAmplitude = ampData.asFloat();
MDataHandle freqData = data.inputValue( frequency, &returnStatus );
McheckErr( returnStatus, "ERROR getting frequency\n" );
noiseFreq = freqData.asFloat();
// Get the time.
//
MDataHandle timeData = data.inputValue( time, &returnStatus );
McheckErr( returnStatus, "ERROR getting time data handle\n" );
MTime time = timeData.asTime();
float seconds = (float)time.as( MTime::kSeconds );
// Easiest way to modify frequency is by modifying the time
//
seconds = seconds * noiseFreq;
// We have the information we need now. We'll apply noise to the
// points upon the lattice
//
unsigned s, t, u;
lattFn.getDivisions( s, t, u );
// match up the divisions in the lattices
//
outLattFn.setDivisions( s, t, u );
for ( unsigned i = 0; i < s; i++ ) {
for ( unsigned j = 0; j < t; j++ ) {
for ( unsigned k = 0; k < u; k++ ) {
MPoint & point = lattFn.point( i, j, k );
MPoint & outPoint = outLattFn.point( i, j, k );
pnt noisePnt = noise::atPointAndTime( (float)point.x, (float)point.y,
(float)point.z, seconds );
// Make noise between -1 and 1 instead of 0 and 1
//
noisePnt.x = ( noisePnt.x * 2.0F ) - 1.0F;
noisePnt.y = ( noisePnt.y * 2.0F ) - 1.0F;
noisePnt.z = ( noisePnt.z * 2.0F ) - 1.0F;
outPoint.x = point.x + ( noisePnt.x * noiseAmplitude );
outPoint.y = point.y + ( noisePnt.y * noiseAmplitude );
outPoint.z = point.z + ( noisePnt.z * noiseAmplitude );
}
}
}
outputData.set( latticeData );
data.setClean(plug);
} else {
return MS::kUnknownParameter;
}
return MS::kSuccess;
}
void* latticeNoiseNode::creator()
{
return new latticeNoiseNode;
}
MStatus latticeNoiseNode::initialize()
{
MFnUnitAttribute unitAttr;
MFnTypedAttribute typedAttr;
MStatus stat;
input = typedAttr.create( "input", "in", MFnData::kLattice, &stat );
if ( !stat ) {
stat.perror("ERROR creating latticeNoiseNode input lattice attribute");
return stat;
}
amplitude = numAttr.create( "amplitude", "amp",
DEF_AMPLITUDE,
&stat );
if ( !stat ) {
stat.perror("ERROR creating latticeNoiseNode amplitude attribute");
return stat;
}
frequency = numAttr.create( "frequency", "fq",
DEF_FREQ,
&stat );
if ( !stat ) {
stat.perror("ERROR creating latticeNoiseNode frequency attribute");
return stat;
}
time = unitAttr.create( "time", "tm", MFnUnitAttribute::kTime,
0.0, &stat );
if ( !stat ) {
stat.perror("ERROR creating latticeNoiseNode time attribute");
return stat;
}
output = typedAttr.create( "output", "out", MFnData::kLattice, &stat );
if ( !stat ) {
stat.perror("ERROR creating latticeNoiseNode output attribute");
return stat;
}
typedAttr.setWritable(false);
stat = addAttribute( input );
if (!stat) { stat.perror("addAttribute"); return stat;}
stat = addAttribute( amplitude );
if (!stat) { stat.perror("addAttribute"); return stat;}
stat = addAttribute( frequency );
if (!stat) { stat.perror("addAttribute"); return stat;}
stat = addAttribute( time );
if (!stat) { stat.perror("addAttribute"); return stat;}
stat = addAttribute( output );
if (!stat) { stat.perror("addAttribute"); return stat;}
stat = attributeAffects( input, output );
if (!stat) { stat.perror("attributeAffects"); return stat;}
stat = attributeAffects( amplitude, output );
if (!stat) { stat.perror("attributeAffects"); return stat;}
stat = attributeAffects( frequency, output );
if (!stat) { stat.perror("attributeAffects"); return stat;}
stat = attributeAffects( time, output );
if (!stat) { stat.perror("attributeAffects"); return stat;}
return MS::kSuccess;
}