- Main Page
- Related Pages
- Modules
- Classes
- Examples

# torusField.h

    //-
    // ==========================================================================
    // 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.
    // ==========================================================================
    //+

    //  Description
    //  The torusField node implements an attraction-and-repel field.
    //
    //  The field repels all objects between itself and repelDistance attribute
    //  and attracts objects greater than attractDistance attribute from itself.
    //  This will eventually result in the objects clustering
    //  in a torus shape around the field.
    //

    #include <maya/MIOStream.h>
    #include <maya/MVector.h>
    #include <maya/MObject.h>
    #include <maya/MPlug.h>
    #include <maya/MDataBlock.h>
    #include <maya/MFnPlugin.h>
    #include <maya/MPxFieldNode.h>

    #if defined(OSMac_MachO_)
    #include <OpenGL/gl.h>
    #else
    #include <GL/gl.h>
    #endif

    #define McheckErr(stat, msg)        \
        if ( MS::kSuccess != stat )     \
        {                               \
            cerr << msg;                \
            return MS::kFailure;        \
        }

    class torusField: public MPxFieldNode
    {
    public:
        torusField() {};
        virtual ~torusField() {};

        static void     *creator();
        static MStatus  initialize();

        // will compute output force.
        //
        virtual MStatus compute( const MPlug& plug, MDataBlock& block );

        virtual void    draw (  M3dView  & view, const  MDagPath  & path,  M3dView::DisplayStyle  style, M3dView:: DisplayStatus );

        virtual MStatus getForceAtPoint(const MVectorArray& point,
                                const MVectorArray& velocity,
                                const MDoubleArray& mass,
                                MVectorArray& force,
                                double deltaTime);

        virtual MStatus iconSizeAndOrigin(  GLuint& width,
                            GLuint& height,
                            GLuint& xbo,
                            GLuint& ybo   );
        virtual MStatus iconBitmap(GLubyte* bitmap);

        //
        // attributes.
        //

        // minimum distance from field at which repel is applied
        //
        static MObject  aMinDistance;

        // min distance from field at which the force attracts
        //
        static MObject  aAttractDistance;

        // max distance from field at which the force repels.
        //
        static MObject  aRepelDistance;

        // drag exerted on the attractRepel force.
        //
        static MObject  aDrag;

        // amplitude/magnitude of the swarm force.
        //
        static MObject  aSwarmAmplitude;

        // frequency of the swarm force.
        //
        static MObject  aSwarmFrequency;

        // phase of the swarm force.
        //
        static MObject  aSwarmPhase;

        // Other data members
        //
        static MTypeId  id;

    private:

        // methods to compute output force.
        //
        void    applyNoMaxDist( MDataBlock& block,
                                const MVectorArray &points,
                                const MVectorArray &velocities,
                                const MDoubleArray &masses,
                                MVectorArray &outputForce );

        void    applyMaxDist( MDataBlock& block,
                                const MVectorArray &points,
                                const MVectorArray &velocities,
                                const MDoubleArray &masses,
                                MVectorArray &outputForce );

        void    ownerPosition( MDataBlock& block, MVectorArray &vArray );
        MStatus getWorldPosition( MVector &vector );
        MStatus getWorldPosition( MDataBlock& block, MVector &vector );
        void    noiseFunction( double *inputNoise, double *out );

        // methods to get attribute value.
        //
        double  magnitudeValue( MDataBlock& block );
        double  attenuationValue( MDataBlock& block );
        double  maxDistanceValue( MDataBlock& block );
        bool    useMaxDistanceValue( MDataBlock& block );
        bool    applyPerVertexValue( MDataBlock& block );

        // methods to get attribute value of local attributes.
        //
        double  minDistanceValue( MDataBlock& block );
        double  attractDistanceValue( MDataBlock& block );
        double  repelDistanceValue( MDataBlock& block );
        double  dragValue( MDataBlock& block );
        double  swarmAmplitudeValue( MDataBlock& block );
        double  swarmFrequencyValue( MDataBlock& block );
        double  swarmPhaseValue( MDataBlock& block );

        MStatus ownerCentroidValue( MDataBlock& block, MVector &vector );
    };

    // inlines
    //
    inline double torusField::magnitudeValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( mMagnitude, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline double torusField::attenuationValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( mAttenuation, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline double torusField::maxDistanceValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( mMaxDistance, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline bool torusField::useMaxDistanceValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( mUseMaxDistance, &status );

        bool value = false;
        if( status == MS::kSuccess )
            value = hValue.asBool();

        return( value );
    }

    inline bool torusField::applyPerVertexValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( mApplyPerVertex, &status );

        bool value = false;
        if( status == MS::kSuccess )
            value = hValue.asBool();

        return( value );
    }

    inline double torusField::minDistanceValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( aMinDistance, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline double torusField::attractDistanceValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( aAttractDistance, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline double torusField::repelDistanceValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( aRepelDistance, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline double torusField::dragValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( aDrag, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline double torusField::swarmAmplitudeValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( aSwarmAmplitude, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline double torusField::swarmFrequencyValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( aSwarmFrequency, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline double torusField::swarmPhaseValue( MDataBlock& block )
    {
        MStatus status;

        MDataHandle hValue = block.inputValue( aSwarmPhase, &status );

        double value = 0.0;
        if( status == MS::kSuccess )
            value = hValue.asDouble();

        return( value );
    }

    inline MStatus torusField::ownerCentroidValue(MDataBlock& block,MVector &vector)
    {
        MStatus status;

        MDataHandle hValueX = block.inputValue( mOwnerCentroidX, &status );
        MDataHandle hValueY = block.inputValue( mOwnerCentroidY, &status );
        MDataHandle hValueZ = block.inputValue( mOwnerCentroidZ, &status );

        if( status == MS::kSuccess )
        {
            vector[0] = hValueX.asDouble();
            vector[1] = hValueY.asDouble();
            vector[2] = hValueZ.asDouble();
        }

        return( status );
    }