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

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

    #include <maya/MIOStream.h>
    #include <math.h>
    #include <maya/MSimple.h>
    #include <maya/MGlobal.h>
    #include <maya/MDagPath.h>
    #include <maya/MSelectionList.h>
    #include <maya/MObjectArray.h>
    #include <maya/MFnWeightGeometryFilter.h>
    #include <maya/MSyntax.h>
    #include <maya/MArgDatabase.h>
    #include <maya/MItGeometry.h>
    #include <maya/MPoint.h>

    #define kSineFlag                               "-s"
    #define kSineFlagLong                           "-sine"
    #define kSineDistanceFlag                       "-sd"
    #define kSineDistanceFlagLong                   "-sineDistance"
    #define kSineDistance2Flag                      "-sd2"
    #define kSineDistance2FlagLong                  "-sineDistance2"
    #define kDistanceSineDistanceFlag               "-dsd"
    #define kDistanceSineDistanceFlagLong           "-distanceSineDistance"
    #define kInverseDistanceSineDistanceFlag        "-ids"
    #define kInverseDistanceSineDistanceFlagLong    "-inverseDistanceSineDistance"
    #define kDistanceFlag                           "-d"
    #define kDistanceFlagLong                       "-distance"
    #define kDistance2Flag                          "-d2"
    #define kDistance2FlagLong                      "-distance2"
    #define kDistance3Flag                          "-d3"
    #define kDistance3FlagLong                      "-distance3"
    #define kDistance4Flag                          "-d4"
    #define kDistance4FlagLong                      "-distance4"
    #define kInverseDistanceFlag                    "-id"
    #define kInverseDistanceFlagLong                "-inverseDistance"
    #define kInverseDistance2Flag                   "-id2"
    #define kInverseDistance2FlagLong               "-inverseDistance2"
    #define kInverseDistance3Flag                   "-id3"
    #define kInverseDistance3FlagLong               "-inverseDistance3"
    #define kInverseDistance4Flag                   "-id4"
    #define kInverseDistance4FlagLong               "-inverseDistance4"

    class clusterWeightFunctionCmd : public MPxCommand
    {
    public:
        clusterWeightFunctionCmd();
        virtual ~clusterWeightFunctionCmd();
        virtual MStatus doIt(const MArgList &args);
        static void *creator();
        static MSyntax newSyntax();

        enum effectType {
            kSine,
            kSineDistance,
            kSineDistance2,
            kDistanceSineDistance,
            kInverseDistanceSineDistance,
            kDistance,
            kDistance2,
            kDistance3,
            kDistance4,
            kInverseDistance,
            kInverseDistance2,
            kInverseDistance3,
            kInverseDistance4
        };

    private:
        MStatus parseArgs(const MArgList &);
        MStatus performWeighting(MFnWeightGeometryFilter &,
                                 MDagPath &,
                                 MObject &);

        effectType fEffectType;
    };

    clusterWeightFunctionCmd::clusterWeightFunctionCmd()
    {
    }

    clusterWeightFunctionCmd::~clusterWeightFunctionCmd()
    {
    }

    MStatus clusterWeightFunctionCmd::doIt(const MArgList &argList)
    {
        MStatus status;

        MSelectionList list;
        MGlobal::getActiveSelectionList(list);

        // Get the cluster
        MFnWeightGeometryFilter cluster;
        MObject dgNode;
        list.getDependNode(0, dgNode);
        if (!cluster.setObject(dgNode))
            return MS::kFailure;

        // Get the object
        MDagPath dagPath;
        MObject component;
        list.getDagPath(1, dagPath, component);

        status = parseArgs(argList);
        if (MS::kSuccess == status)
            status = performWeighting(cluster, dagPath, component);
        return status;
    }

    void *clusterWeightFunctionCmd::creator()
    {
        return new clusterWeightFunctionCmd;
    }

    MSyntax clusterWeightFunctionCmd::newSyntax()
    {
        MSyntax syntax;

        syntax.addFlag(kSineFlag, kSineFlagLong);
        syntax.addFlag(kSineDistanceFlag, kSineDistanceFlagLong);
        syntax.addFlag(kSineDistance2Flag, kSineDistance2FlagLong);
        syntax.addFlag(kDistanceSineDistanceFlag, kDistanceSineDistanceFlagLong);
        syntax.addFlag(kInverseDistanceSineDistanceFlag,
                       kInverseDistanceSineDistanceFlagLong);
        syntax.addFlag(kDistanceFlag, kDistanceFlagLong);
        syntax.addFlag(kDistance2Flag, kDistance2FlagLong);
        syntax.addFlag(kDistance3Flag, kDistance3FlagLong);
        syntax.addFlag(kDistance4Flag, kDistance4FlagLong);
        syntax.addFlag(kInverseDistanceFlag, kInverseDistanceFlagLong);
        syntax.addFlag(kInverseDistance2Flag, kInverseDistance2FlagLong);
        syntax.addFlag(kInverseDistance3Flag, kInverseDistance3FlagLong);
        syntax.addFlag(kInverseDistance4Flag, kInverseDistance4FlagLong);

        return syntax;
    }

    MStatus clusterWeightFunctionCmd::parseArgs(const MArgList &argList)
    {
        MArgDatabase argData(syntax(), argList);

        if (argData.isFlagSet(kSineFlag)) {
            fEffectType = kSine;
        }
        else if (argData.isFlagSet(kSineDistanceFlag)) {
            fEffectType = kSineDistance;
        }
        else if (argData.isFlagSet(kSineDistance2Flag)) {
            fEffectType = kSineDistance2;
        }
        else if (argData.isFlagSet(kDistanceSineDistanceFlag)) {
            fEffectType = kDistanceSineDistance;
        }
        else if (argData.isFlagSet(kInverseDistanceSineDistanceFlag)) {
            fEffectType = kInverseDistanceSineDistance;
        }
        else if (argData.isFlagSet(kDistanceFlag)) {
            fEffectType = kDistance;
        }
        else if (argData.isFlagSet(kDistance2Flag)) {
            fEffectType = kDistance2;
        }
        else if (argData.isFlagSet(kDistance3Flag)) {
            fEffectType = kDistance3;
        }
        else if (argData.isFlagSet(kDistance4Flag)) {
            fEffectType = kDistance4;
        }
        else if (argData.isFlagSet(kInverseDistanceFlag)) {
            fEffectType = kInverseDistance;
        }
        else if (argData.isFlagSet(kInverseDistance2Flag)) {
            fEffectType = kInverseDistance2;
        }
        else if (argData.isFlagSet(kInverseDistance3Flag)) {
            fEffectType = kInverseDistance3;
        }
        else if (argData.isFlagSet(kInverseDistance4Flag)) {
            fEffectType = kInverseDistance4;
        }

        return MS::kSuccess;
    }

    MStatus clusterWeightFunctionCmd::performWeighting(MFnWeightGeometryFilter &cluster,
                                               MDagPath &dagPath,
                                               MObject &component)
    {
        MStatus status;
        MItGeometry geomIter(dagPath, component, &status);
        MObject comp;
        MObjectArray compArray;
        MDoubleArray weightArray;
        double weight = 0.0;

        if (MS::kSuccess == status) {
            for (; !geomIter.isDone(); geomIter.next()) {
                comp = geomIter.component();

                MPoint pnt = geomIter.position(MSpace::kWorld, &status);

                if (MS::kSuccess != status) {
                    return MS::kFailure;
                }

                if (kSine == fEffectType) {
                    weight = sin(pnt.x)*sin(pnt.z);
                }
                else if (kSineDistance == fEffectType) {
                    double distance = pnt.distanceTo(MPoint::origin);
                    weight = sin(distance);
                }
                else if (kSineDistance2 == fEffectType) {
                    double distance = pnt.distanceTo(MPoint::origin);
                    weight = sin(distance*distance);
                }
                else if (kDistanceSineDistance == fEffectType) {
                    double distance = pnt.distanceTo(MPoint::origin);
                    weight = distance*sin(distance);
                }
                else if (kInverseDistanceSineDistance == fEffectType) {
                    double distance = pnt.distanceTo(MPoint::origin);
                    weight = sin(distance)/(distance+1);
                }
                else if (kDistance == fEffectType) {
                    double distance = pnt.distanceTo(MPoint::origin);
                    weight = distance;
                }
                else if (kDistance2 == fEffectType) {
                    double distance = pnt.distanceTo(MPoint::origin);
                    weight = distance*distance;
                }
                else if (kDistance3 == fEffectType) {
                    double distance = pnt.distanceTo(MPoint::origin);
                    weight = distance*distance*distance;
                }
                else if (kDistance4 == fEffectType) {
                    double distance = pnt.distanceTo(MPoint::origin);
                    weight = distance*distance*distance*distance;
                }
                else if (kInverseDistance == fEffectType) {
                    double dist = pnt.distanceTo(MPoint::origin) + 1;
                    weight = 1/(dist);
                }
                else if (kInverseDistance2 == fEffectType) {
                    double dist = pnt.distanceTo(MPoint::origin) + 1;
                    weight = 1/(dist*dist);
                }
                else if (kInverseDistance3 == fEffectType) {
                    double dist = pnt.distanceTo(MPoint::origin) + 1;
                    weight = 1/(dist*dist*dist);
                }
                else if (kInverseDistance4 == fEffectType) {
                    double dist = pnt.distanceTo(MPoint::origin) + 1;
                    weight = 1/(dist*dist*dist*dist);
                }

                compArray.append(comp);
                weightArray.append(weight);
            }

            unsigned length = compArray.length();
            for (unsigned i = 0; i < length; i++) {
                cluster.setWeight(dagPath, compArray[i], (float) weightArray[i]);
            }

            return MS::kSuccess;
        } else
            return MS::kFailure;
    }

    extern MStatus initializePlugin(MObject obj)
    {
        MStatus status;
        MFnPlugin plugin(obj, PLUGIN_COMPANY, "3.0", "Any");

        status = plugin.registerCommand("clusterWeightFunction",
                                        clusterWeightFunctionCmd::creator,
                                        clusterWeightFunctionCmd::newSyntax);

        if (!status) {
            status.perror("registerCommand");
        }

        return status;
    }

    extern MStatus uninitializePlugin(MObject obj)
    {
        MStatus status;
        MFnPlugin plugin(obj);

        status = plugin.deregisterCommand("clusterWeightFunction");

        if (!status) {
            status.perror("deregisterCommand");
        }

        return status;
    }