//- // ========================================================================== // Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files contain unpublished // information proprietary to Autodesk, Inc. ("Autodesk") and/or its // licensors, which is protected by U.S. and Canadian federal copyright // law and by international treaties. // // The Data is provided for use exclusively by You. You have the right // to use, modify, and incorporate this Data into other products for // purposes authorized by the Autodesk software license agreement, // without fee. // // The copyright notices in the Software and this entire statement, // including the above license grant, this restriction and the // following disclaimer, must be included in all copies of the // Software, in whole or in part, and all derivative works of // the Software, unless such copies or derivative works are solely // in the form of machine-executable object code generated by a // source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. // AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED // WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF // NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR // PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR // TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS // BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, // DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK // AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY // OR PROBABILITY OF SUCH DAMAGES. // // ========================================================================== //+ // // 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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; MFnNumericAttribute numAttr; 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", MFnNumericData::kFloat, DEF_AMPLITUDE, &stat ); if ( !stat ) { stat.perror("ERROR creating latticeNoiseNode amplitude attribute"); return stat; } frequency = numAttr.create( "frequency", "fq", MFnNumericData::kFloat, 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; }