//- // ========================================================================== // Copyright (C) 1995 - 2005 Alias Systems Corp. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files are provided by Alias // Systems Corp. ("Alias") and/or its licensors for the exclusive use of the // Customer (as defined in the Alias Software License Agreement that // accompanies this Alias software). Such Customer has the right to use, // modify, and incorporate the Data into other products and to distribute such // products for use by end-users. // // THE DATA IS PROVIDED "AS IS". ALIAS HEREBY DISCLAIMS ALL WARRANTIES // RELATING TO THE DATA, INCLUDING, WITHOUT LIMITATION, ANY AND ALL EXPRESS OR // IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. IN NO EVENT SHALL ALIAS BE LIABLE FOR ANY DAMAGES // WHATSOEVER, WHETHER DIRECT, INDIRECT, SPECIAL, OR PUNITIVE, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, OR IN EQUITY, // ARISING OUT OF ACCESS TO, USE OF, OR RELIANCE UPON THE DATA. // ========================================================================== //+ // Jitter // // Description: // // This is a dependency graph node which takes a // floating point value as input, adds a random value, // and passes the result on as output. A time input // is used to ensure the output result is repeatable // when played back. A scale input is used to scale // the value beyond 1.0. // // Attributes ( < input, > output ): // // < input: the input float value // < scale: the scalar for the random value (0 - 1.0) // < time: the frame number // // > output: the randomized float value // // Usage: // // Use jitterNode.mel to insert this DG node between // a float value connection in your DG. See that MEL // script for usage information. #include #include #include #include #include #include #include #include #include #include #include #include static unsigned int xRand, yRand, zRand; /* seed */ float randomd() { float result; unsigned int a = xRand/177, b = xRand%177; unsigned int c = yRand/176, d = yRand%176; unsigned int e = zRand/178, f = zRand%178; xRand = (171 * b - 2 * a) % 30269; yRand = (172 * d - 35 * c) % 30307; zRand = (170 * f - 63 * e) % 30323; result = (float) xRand/30269.0f + yRand/30307.0f + zRand/30323.0f; return result - ((int) result); } void seedd(unsigned char nx, unsigned char ny, unsigned char nz) { xRand = nx; yRand = ny; zRand = nz; randomd(); randomd(); randomd(); randomd(); } class jitter : public MPxNode { public: jitter(); virtual ~jitter(); virtual MStatus compute( const MPlug& plug, MDataBlock& data ); static void* creator(); static MStatus initialize(); static MObject time; // The time value. static MObject scale; // Scale of jitter. static MObject input; // The input value. static MObject output; // The jittered-output value. static MTypeId id; }; MTypeId jitter::id( 0x80009 ); MObject jitter::time; MObject jitter::scale; MObject jitter::input; MObject jitter::output; void* jitter::creator() { return new jitter(); } MStatus jitter::initialize() { MFnNumericAttribute nAttr; MStatus stat; time = nAttr.create( "time", "tm", MFnNumericData::kFloat, 0.0 ); nAttr.setStorable(true); scale = nAttr.create( "scale", "sc", MFnNumericData::kFloat, 1.0 ); nAttr.setStorable(true); input = nAttr.create( "input", "in", MFnNumericData::kFloat, 0.0 ); nAttr.setStorable(true); output = nAttr.create( "output", "out", MFnNumericData::kFloat, 0.0 ); nAttr.setWritable(false); nAttr.setStorable(false); stat = addAttribute( time ); if (!stat) { stat.perror("addAttribute"); return stat;} stat = addAttribute( scale ); if (!stat) { stat.perror("addAttribute"); return stat;} stat = addAttribute( input ); if (!stat) { stat.perror("addAttribute"); return stat;} stat = addAttribute( output ); if (!stat) { stat.perror("addAttribute"); return stat;} stat = attributeAffects( time, output ); if (!stat) { stat.perror("attributeAffects"); return stat;} stat = attributeAffects( scale, output ); if (!stat) { stat.perror("attributeAffects"); return stat;} stat = attributeAffects( input, output ); if (!stat) { stat.perror("attributeAffects"); return stat;} return MS::kSuccess; } jitter::jitter() {} jitter::~jitter() {} // Compute the offset and add it to input // as the output from this node. MStatus jitter::compute( const MPlug& plug, MDataBlock& data ) { MStatus returnStatus; if( plug == output ) { MDataHandle timeData = data.inputValue( time, &returnStatus ); MDataHandle scaleData = data.inputValue( scale, &returnStatus ); MDataHandle inputData = data.inputValue( input, &returnStatus ); if( returnStatus != MS::kSuccess ) cerr << "ERROR getting data\n"; else { float currentFrame = timeData.asFloat(); float scaleFactor = scaleData.asFloat(); float inValue = inputData.asFloat(); // This is where we jitter the value unsigned char seed = (unsigned char)currentFrame; seedd( seed, seed * 17, seed * 23 ); float tmp = randomd(); float result = ( tmp - 0.5f ) * scaleFactor + inValue; MDataHandle outHandle = data.outputValue( jitter::output ); outHandle.set( result ); data.setClean(plug); } } else { return MS::kUnknownParameter; } return MS::kSuccess; } MStatus initializePlugin( MObject obj ) { MStatus status; MFnPlugin plugin( obj, "Alias", "3.0", "Any"); status = plugin.registerNode( "jitter", jitter::id, jitter::creator, jitter::initialize ); if (!status) { status.perror("registerNode"); return status; } return status; } MStatus uninitializePlugin( MObject obj) { MStatus status; MFnPlugin plugin( obj ); status = plugin.deregisterNode( jitter::id ); if (!status) { status.perror("deregisterNode"); return status; } return status; }