SOP/SOP_PointWave.C

/*
 * Copyright (c) 2013
 *      Side Effects Software Inc.  All rights reserved.
 *
 * Redistribution and use of Houdini Development Kit samples in source and
 * binary forms, with or without modification, are permitted provided that the
 * following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. The name of Side Effects Software may not be used to endorse or
 *    promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *----------------------------------------------------------------------------
 * The PointWave SOP.  This SOP PointWaves the geometry onto a plane.
 */

#include <UT/UT_DSOVersion.h>
#include <UT/UT_Math.h>
#include <UT/UT_Matrix3.h>
#include <UT/UT_Matrix4.h>
#include <GU/GU_Detail.h>
#include <GU/GU_PrimPoly.h>
#include <PRM/PRM_Include.h>
#include <OP/OP_Operator.h>
#include <OP/OP_OperatorTable.h>
#include <SOP/SOP_Guide.h>
#include "SOP_PointWave.h"

using namespace HDK_Sample;

void
newSopOperator(OP_OperatorTable *table)
{
     table->addOperator(new OP_Operator("hdk_pointwave",
                                        "Point Wave",
                                         SOP_PointWave::myConstructor,
                                         SOP_PointWave::myTemplateList,
                                         1,
                                         1,
                                         0));
}

static PRM_Name        names[] = {
    PRM_Name("amp",     "Amplitude"),
    PRM_Name("phase",   "Phase"),
    PRM_Name("period",  "Period"),
};

PRM_Template
SOP_PointWave::myTemplateList[] = {
    PRM_Template(PRM_STRING,    1, &PRMgroupName, 0, &SOP_Node::pointGroupMenu),
    PRM_Template(PRM_FLT_J,     1, &names[0], PRMoneDefaults, 0,
                                   &PRMscaleRange),
    PRM_Template(PRM_FLT_J,     1, &names[1], PRMzeroDefaults),
    PRM_Template(PRM_FLT_J,     1, &names[2], PRMoneDefaults),
    PRM_Template(),
};


OP_Node *
SOP_PointWave::myConstructor(OP_Network *net, const char *name, OP_Operator *op)
{
    return new SOP_PointWave(net, name, op);
}

SOP_PointWave::SOP_PointWave(OP_Network *net, const char *name, OP_Operator *op)
        : SOP_Node(net, name, op), myGroup(0)
{
}

SOP_PointWave::~SOP_PointWave() {}

OP_ERROR
SOP_PointWave::cookInputGroups(OP_Context &context, int alone)
{
    // The SOP_Node::cookInputPointGroups() provides a good default
    // implementation for just handling a point selection.
    return cookInputPointGroups(context, myGroup, myDetailGroupPair, alone);
}

OP_ERROR
SOP_PointWave::cookMySop(OP_Context &context)
{
    GEO_Point           *ppt;
    double               t;
    float                amp, period, phase;

    // Before we do anything, we must lock our inputs.  Before returning,
    //  we have to make sure that the inputs get unlocked.
    if (lockInputs(context) >= UT_ERROR_ABORT)
        return error();

    t = context.getTime();

    // Duplicate our incoming geometry with the hint that we only
    // altered points.  Thus if we our input was unchanged we can
    // easily roll back our changes by copying point values.
    duplicatePointSource(0, context);

    // We evaluate our parameters outside the loop for speed.  If we
    // wanted local variable support, we'd have to do more setup
    // (see SOP_Flatten) and also move these inside the loop.
    phase = PHASE(t);
    amp = AMP(t);
    period = PERIOD(t);

    // Here we determine which groups we have to work on.  We only
    //  handle point groups.
    if (error() < UT_ERROR_ABORT && cookInputGroups(context) < UT_ERROR_ABORT)
    {
        FOR_ALL_OPT_GROUP_POINTS(gdp, myGroup, ppt)
        {
            UT_Vector4          p;

            p = ppt->getPos();

            p.y() += SYSsin( (p.x() / period + phase) * M_PI * 2 ) * amp;

            ppt->getPos() = p;
        }
    }

    // Notify the display cache that we have directly edited
    // points, this lets NURBs surfaces know that they need to rebuild,
    // for example.
    gdp->notifyCache(GU_CACHE_ALL);
    unlockInputs();
    
    return error();
}

Generated on Mon Jan 28 00:45:45 2013 for HDK by  doxygen 1.5.9