#include <maya/MIOStream.h>
#include <math.h>
#include "torusField.h"
#include <maya/MTime.h>
#include <maya/MVectorArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MMatrix.h>
#include <maya/MArrayDataBuilder.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnCompoundAttribute.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MFnVectorArrayData.h>
#include <maya/MFnDoubleArrayData.h>
#include <maya/MFnMatrixData.h>
MObject torusField::aAttractDistance;
MObject torusField::aRepelDistance;
MObject torusField::aSwarmAmplitude;
MObject torusField::aSwarmFrequency;
void *torusField::creator()
{
return new torusField;
}
{
status = addAttribute( aMinDistance );
McheckErr(status, "ERROR adding aMinDistance attribute.\n");
aAttractDistance = numAttr.
create(
"attractDistance",
"ad",
status = addAttribute( aAttractDistance );
McheckErr(status, "ERROR adding aAttractDistance attribute.\n");
aRepelDistance = numAttr.
create(
"repelDistance",
"rd",
status = addAttribute( aRepelDistance );
McheckErr(status, "ERROR adding aRepelDistance attribute.\n");
status = addAttribute( aDrag );
McheckErr(status, "ERROR adding aDrag attribute.\n");
aSwarmAmplitude = numAttr.
create(
"swarmAmplitude",
"samp",
status = addAttribute( aSwarmAmplitude );
McheckErr(status, "ERROR adding aSwarmAmplitude attribute.\n");
aSwarmFrequency = numAttr.
create(
"swarmFrequency",
"sfrq",
status = addAttribute( aSwarmFrequency );
McheckErr(status, "ERROR adding aSwarmFrequency attribute.\n");
status = addAttribute( aSwarmPhase );
McheckErr(status, "ERROR adding aSwarmPhase attribute.\n");
return( MS::kSuccess );
}
{
if( !(plug == mOutputForce) )
return( MS::kUnknownParameter );
McheckErr(status, "ERROR in plug.logicalIndex.\n");
McheckErr(status,"ERROR in hInputArray = block.outputArrayValue().\n");
McheckErr(status, "ERROR: hInputArray.jumpToElement failed.\n");
McheckErr(status, "ERROR in hCompond=hInputArray.inputValue\n");
McheckErr(status, "ERROR in fnPosition.array(), not find points.\n");
McheckErr(status, "ERROR in fnVelocity.array(), not find velocities.\n");
McheckErr(status, "ERROR in fnMass.array(), not find masses.\n");
bool useMaxDistSet = useMaxDistanceValue( block );
if( useMaxDistSet )
{
applyMaxDist( block, points, velocities, masses, forceArray );
}
else
{
applyNoMaxDist( block, points, velocities, masses, forceArray );
}
McheckErr(status, "ERROR in hOutArray = block.outputArrayValue.\n");
McheckErr(status, "ERROR in bOutArray = hOutArray.builder.\n");
McheckErr(status, "ERROR in hOut = bOutArray.addElement.\n");
MObject dOutputForce = fnOutputForce.
create( forceArray, &status );
McheckErr(status, "ERROR in dOutputForce = fnOutputForce.create\n");
hOut.
set( dOutputForce );
return( MS::kSuccess );
}
void torusField::applyNoMaxDist
(
)
{
return;
double magValue = magnitudeValue( block );
double minDist = minDistanceValue( block );
double attractDist = attractDistanceValue( block );
double repelDist = repelDistanceValue( block );
double dragMag = dragValue( block );
double swarmAmp = swarmAmplitudeValue( block );
ownerPosition( block, posArray );
int fieldPosCount = posArray.
length();
int receptorSize = points.
length();
if (dragMag <= 0)
{
if (swarmAmp <= 0)
{
for (int ptIndex = 0; ptIndex < receptorSize; ptIndex ++ )
{
const MVector &receptorPoint = points[ptIndex];
for(int i = fieldPosCount; --i>=0; )
{
MVector difference = (receptorPoint-posArray[i]);
double distance = difference.
length();
if (distance < minDist) continue;
if (distance <= repelDist)
forceV += difference * magValue;
else if (distance >= attractDist)
forceV += -difference * magValue;
}
}
}
else
{
for (int ptIndex = 0; ptIndex < receptorSize; ptIndex ++ )
{
const MVector &receptorPoint = points[ptIndex];
double distance = 0.0;
int i;
for(i = fieldPosCount; --i>=0; )
{
MVector difference = (receptorPoint-posArray[i]);
distance = difference.
length();
if (distance < minDist) continue;
if (distance <= repelDist)
forceV += difference * magValue;
else if (distance >= attractDist)
forceV += -difference * magValue;
}
if ( distance >= repelDist && distance <= attractDist)
{
double frequency = swarmFrequencyValue( block );
MVector phase( 0.0, 0.0, swarmPhaseValue(block) );
for(i = fieldPosCount; --i >= 0;)
{
MVector difference = receptorPoint - posArray[i];
difference = (difference + phase) * frequency;
double *noiseEffect = &difference.
x;
if( (noiseEffect[0] < -2147483647.0) ||
(noiseEffect[0] > 2147483647.0) ||
(noiseEffect[1] < -2147483647.0) ||
(noiseEffect[1] > 2147483647.0) ||
(noiseEffect[2] < -2147483647.0) ||
(noiseEffect[2] > 2147483647.0) )
continue;
double noiseOut[4];
noiseFunction( noiseEffect, noiseOut );
MVector swarmForce( noiseOut[0] * swarmAmp,
noiseOut[1] * swarmAmp,
noiseOut[2] * swarmAmp );
forceV += swarmForce;
}
}
}
}
}
else
{
if (swarmAmp <= 0)
{
for (int ptIndex = 0; ptIndex < receptorSize; ptIndex ++ )
{
const MVector& receptorPoint = points[ptIndex];
double distance = 0.0;
for(int i = fieldPosCount; --i>=0; )
{
MVector difference = (receptorPoint-posArray[i]);
distance = difference.
length();
if (distance < minDist) continue;
if (distance <= repelDist)
forceV += difference * magValue;
else if (distance >= attractDist)
forceV += -difference * magValue;
}
if ( distance >= repelDist && distance <= attractDist)
{
if (fieldPosCount > 0)
{
dragForceV = velocities[ptIndex] *
(-dragMag) * fieldPosCount;
forceV += dragForceV;
}
}
}
}
else
{
for (int ptIndex = 0; ptIndex < receptorSize; ptIndex ++ )
{
const MVector &receptorPoint = points[ptIndex];
double distance = 0.0;
int i;
for(i = fieldPosCount; --i>=0; )
{
MVector difference = (receptorPoint-posArray[i]);
distance = difference.
length();
if (distance < minDist) continue;
if (distance <= repelDist)
forceV += difference * magValue;
else if (distance >= attractDist)
forceV += -difference * magValue;
}
if ( distance >= repelDist && distance <= attractDist)
{
if (fieldPosCount > 0)
{
dragForceV = velocities[ptIndex] *
(-dragMag) * fieldPosCount;
forceV += dragForceV;
}
double frequency = swarmFrequencyValue( block );
MVector phase( 0.0, 0.0, swarmPhaseValue(block) );
for(i = fieldPosCount; --i>=0; )
{
MVector difference = receptorPoint - posArray[i];
difference = (difference + phase) * frequency;
double *noiseEffect = &difference.
x;
if( (noiseEffect[0] < -2147483647.0) ||
(noiseEffect[0] > 2147483647.0) ||
(noiseEffect[1] < -2147483647.0) ||
(noiseEffect[1] > 2147483647.0) ||
(noiseEffect[2] < -2147483647.0) ||
(noiseEffect[2] > 2147483647.0) )
continue;
double noiseOut[4];
noiseFunction( noiseEffect, noiseOut );
MVector swarmForce( noiseOut[0] * swarmAmp,
noiseOut[1] * swarmAmp,
noiseOut[2] * swarmAmp );
forceV += swarmForce;
}
}
}
}
}
}
void torusField::applyMaxDist
(
)
{
return;
double magValue = magnitudeValue( block );
double attenValue = attenuationValue( block );
double maxDist = maxDistanceValue( block );
double minDist = minDistanceValue( block );
double attractDist = attractDistanceValue( block );
double repelDist = repelDistanceValue( block );
double dragMag = dragValue( block );
double swarmAmp = swarmAmplitudeValue( block );
ownerPosition( block, posArray );
int fieldPosCount = posArray.
length();
int receptorSize = points.
length();
if (attenValue > 0.0)
{
for (int ptIndex = 0; ptIndex < receptorSize; ptIndex ++ )
{
const MVector &receptorPoint = points[ptIndex];
for(int i = fieldPosCount; --i>=0; )
{
MVector difference = receptorPoint-posArray[i];
double distance = difference.
length();
if (distance <= maxDist && distance >= minDist )
{
double force = magValue *
(pow((1.0-(distance/maxDist)),attenValue));
forceV = difference * force;
if ( distance >= repelDist && distance <= attractDist)
{
if (fieldPosCount > 0 && dragMag > 0)
{
dragForceV = velocities[ptIndex] *
(-dragMag) * fieldPosCount;
forceV += dragForceV;
}
if (swarmAmp > 0)
{
double frequency = swarmFrequencyValue( block );
MVector phase( 0.0, 0.0, swarmPhaseValue(block) );
difference = receptorPoint - posArray[i];
difference = (difference + phase) * frequency;
double *noiseEffect = &difference.
x;
if( (noiseEffect[0] < -2147483647.0) ||
(noiseEffect[0] > 2147483647.0) ||
(noiseEffect[1] < -2147483647.0) ||
(noiseEffect[1] > 2147483647.0) ||
(noiseEffect[2] < -2147483647.0) ||
(noiseEffect[2] > 2147483647.0) )
continue;
double noiseOut[4];
noiseFunction( noiseEffect, noiseOut );
MVector swarmForce( noiseOut[0] * swarmAmp,
noiseOut[1] * swarmAmp,
noiseOut[2] * swarmAmp );
forceV += swarmForce;
}
}
}
if (maxDist > 0.0) forceV *= falloffCurve(distance/maxDist);
sumForceV += forceV;
}
outputForce.
append( sumForceV );
}
}
else
{
for (int ptIndex = 0; ptIndex < receptorSize; ptIndex ++ )
{
const MVector & receptorPoint = points[ptIndex];
int i;
for(i = fieldPosCount; --i>=0; )
{
MVector difference = (receptorPoint-posArray[i]);
double distance = difference.
length();
if (distance < minDist || distance > maxDist) continue;
if (distance <= repelDist)
forceV = difference * magValue;
else if (distance >= attractDist)
forceV = -difference * magValue;
if ( distance >= repelDist && distance <= attractDist)
{
if (fieldPosCount > 0 && dragMag > 0)
{
dragForceV = velocities[ptIndex] *
(-dragMag) * fieldPosCount;
forceV += dragForceV;
}
if (swarmAmp > 0)
{
double frequency = swarmFrequencyValue( block );
MVector phase( 0.0, 0.0, swarmPhaseValue(block) );
for(i = fieldPosCount; --i >= 0;)
{
difference = receptorPoint - posArray[i];
difference = (difference + phase) * frequency;
double *noiseEffect = &difference.
x;
if( (noiseEffect[0] < -2147483647.0) ||
(noiseEffect[0] > 2147483647.0) ||
(noiseEffect[1] < -2147483647.0) ||
(noiseEffect[1] > 2147483647.0) ||
(noiseEffect[2] < -2147483647.0) ||
(noiseEffect[2] > 2147483647.0) )
continue;
double noiseOut[4];
noiseFunction( noiseEffect, noiseOut );
MVector swarmForce( noiseOut[0] * swarmAmp,
noiseOut[1] * swarmAmp,
noiseOut[2] * swarmAmp );
forceV += swarmForce;
}
}
}
if (maxDist > 0.0) forceV *= falloffCurve(distance/maxDist);
sumForceV += forceV;
}
outputForce.
append( sumForceV );
}
}
}
void torusField::ownerPosition
(
)
{
if( applyPerVertexValue(block) )
{
if( status == MS::kSuccess )
{
if( status == MS::kSuccess )
{
for(
unsigned int i = 0; i < posArray.
length(); i ++ )
ownerPosArray.
append( posArray[i] );
}
else
{
status = getWorldPosition( worldPos );
ownerPosArray.
append( worldPos );
}
}
else
{
status = getWorldPosition( worldPos );
ownerPosArray.
append( worldPos );
}
}
else
{
status = ownerCentroidValue( block, centroidV );
if( status == MS::kSuccess )
{
ownerPosArray.
append( centroidV );
}
else
{
status = getWorldPosition( worldPos );
ownerPosArray.
append( worldPos );
}
}
}
{
MObject worldMatrixAttr = fnThisNode.attribute(
"worldMatrix" );
MPlug matrixPlug( thisNode, worldMatrixAttr );
matrixPlug = matrixPlug.elementByLogicalIndex( 0 );
status = matrixPlug.getValue( matrixObject );
if( !status )
{
status.
perror(
"torusField::getWorldPosition: get matrixObject");
return( status );
}
if( !status )
{
status.
perror(
"torusField::getWorldPosition: get worldMatrixData");
return( status );
}
if( !status )
{
status.
perror(
"torusField::getWorldPosition: get worldMatrix");
return( status );
}
vector[0] = worldMatrix( 3, 0 );
vector[1] = worldMatrix( 3, 1 );
vector[2] = worldMatrix( 3, 2 );
return( status );
}
{
MObject worldMatrixAttr = fnThisNode.attribute(
"worldMatrix" );
MPlug matrixPlug( thisNode, worldMatrixAttr );
matrixPlug = matrixPlug.elementByLogicalIndex( 0 );
McheckErr(status, "ERROR getting hWMatrix from dataBlock.\n");
if( status == MS::kSuccess )
{
vector[0] = wMatrix(3, 0);
vector[1] = wMatrix(3, 1);
vector[2] = wMatrix(3, 2);
}
return( status );
}
double )
{
bool useMaxDistSet = useMaxDistanceValue( block );
if( useMaxDistSet )
{
applyMaxDist( block, points, velocities, masses, forceArray );
}
else
{
applyNoMaxDist( block, points, velocities, masses, forceArray );
}
return MS::kSuccess;
}
MStatus torusField::iconSizeAndOrigin( GLuint& width,
GLuint& height,
GLuint& xbo,
GLuint& ybo )
{
width = 32;
height = 32;
xbo = 4;
ybo = 4;
return MS::kSuccess;
}
MStatus torusField::iconBitmap(GLubyte* bitmap)
{
bitmap[0] = 0x18;
bitmap[4] = 0x66;
bitmap[8] = 0xC3;
bitmap[12] = 0x81;
bitmap[16] = 0x81;
bitmap[20] = 0xC3;
bitmap[24] = 0x66;
bitmap[28] = 0x18;
return MS::kSuccess;
}
#define rand3a(x,y,z) frand(67*(x)+59*(y)+71*(z))
#define rand3b(x,y,z) frand(73*(x)+79*(y)+83*(z))
#define rand3c(x,y,z) frand(89*(x)+97*(y)+101*(z))
#define rand3d(x,y,z) frand(103*(x)+107*(y)+109*(z))
int xlim[3][2];
double xarg[3];
double frand( int s )
{
s = s << 13^s;
return(1. - ((s*(s*s*15731+789221)+1376312589)&0x7fffffff)/1073741824.);
}
double hermite( double p0, double p1, double r0, double r1, double t )
{
double t2, t3, _3t2, _2t3 ;
t2 = t * t;
t3 = t2 * t;
_3t2 = 3. * t2;
_2t3 = 2. * t3 ;
return(p0*(_2t3-_3t2+1) + p1*(-_2t3+_3t2) + r0*(t3-2.*t2+t) + r1*(t3-t2));
}
void interpolate( double f[4], int i, int n )
{
double f0[4], f1[4] ;
if( n == 0 )
{
f[0] = rand3a( xlim[0][i&1], xlim[1][i>>1&1], xlim[2][i>>2] );
f[1] = rand3b( xlim[0][i&1], xlim[1][i>>1&1], xlim[2][i>>2] );
f[2] = rand3c( xlim[0][i&1], xlim[1][i>>1&1], xlim[2][i>>2] );
f[3] = rand3d( xlim[0][i&1], xlim[1][i>>1&1], xlim[2][i>>2] );
return;
}
n--;
interpolate( f0, i, n );
interpolate( f1, i| 1<<n, n );
f[0] = (1. - xarg[n]) * f0[0] + xarg[n] * f1[0];
f[1] = (1. - xarg[n]) * f0[1] + xarg[n] * f1[1];
f[2] = (1. - xarg[n]) * f0[2] + xarg[n] * f1[2];
f[3] = hermite( f0[3], f1[3], f0[n], f1[n], xarg[n] );
}
void torusField::noiseFunction( double *inNoise, double *out )
{
xlim[0][0] = (int)floor( inNoise[0] );
xlim[0][1] = xlim[0][0] + 1;
xlim[1][0] = (int)floor( inNoise[1] );
xlim[1][1] = xlim[1][0] + 1;
xlim[2][0] = (int)floor( inNoise[2] );
xlim[2][1] = xlim[2][0] + 1;
xarg[0] = inNoise[0] - xlim[0][0];
xarg[1] = inNoise[1] - xlim[1][0];
xarg[2] = inNoise[2] - xlim[2][0];
interpolate( out, 0, 3 ) ;
}
#define TORUS_PI 3.14159265
#define TORUS_2PI 2*TORUS_PI
#define EDGES 30
#define SEGMENTS 20
{
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
_OPENMAYA_POP_WARNING
for (int j = 0; j < SEGMENTS; j++ )
{
glPushMatrix();
glRotatef( GLfloat(360 * j / SEGMENTS), 0.0, 1.0, 0.0 );
glTranslatef( 1.5, 0.0, 0.0 );
for (int i = 0; i < EDGES; i++ )
{
glBegin(GL_LINE_STRIP);
float p0 = float( TORUS_2PI * i / EDGES );
float p1 = float( TORUS_2PI * (i+1) / EDGES );
glVertex2f( cos(p0), sin(p0) );
glVertex2f( cos(p1), sin(p1) );
glEnd();
}
glPopMatrix();
}
_OPENMAYA_DEPRECATION_PUSH_AND_DISABLE_WARNING
_OPENMAYA_POP_WARNING
}
{
MFnPlugin plugin(obj, PLUGIN_COMPANY,
"3.0",
"Any");
status = plugin.registerNode( "torusField", torusField::id,
&torusField::creator, &torusField::initialize,
if (!status) {
status.
perror(
"registerNode");
return status;
}
return status;
}
{
status = plugin.deregisterNode( torusField::id );
if (!status) {
status.
perror(
"deregisterNode");
return status;
}
return status;
}