#include <UT/UT_DSOVersion.h>
#include <UT/UT_Interrupt.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_Flatten.h"
using namespace HDK_Sample;
void
newSopOperator(OP_OperatorTable *table)
{
table->addOperator(new OP_Operator("hdk_flatten",
"Flatten",
SOP_Flatten::myConstructor,
SOP_Flatten::myTemplateList,
1,
1,
0));
}
static PRM_Name names[] = {
PRM_Name("usedir", "Use Direction Vector"),
PRM_Name("dist", "Distance"),
};
PRM_Template
SOP_Flatten::myTemplateList[] = {
PRM_Template(PRM_STRING, 1, &PRMgroupName, 0, &SOP_Node::pointGroupMenu),
PRM_Template(PRM_FLT_J, 1, &names[1], PRMzeroDefaults, 0,
&PRMscaleRange),
PRM_Template(PRM_TOGGLE, 1, &names[0]),
PRM_Template(PRM_ORD, 1, &PRMorientName, 0, &PRMplaneMenu),
PRM_Template(PRM_DIRECTION, 3, &PRMdirectionName, PRMzaxisDefaults),
PRM_Template(),
};
OP_Node *
SOP_Flatten::myConstructor(OP_Network *net, const char *name, OP_Operator *op)
{
return new SOP_Flatten(net, name, op);
}
SOP_Flatten::SOP_Flatten(OP_Network *net, const char *name, OP_Operator *op)
: SOP_Node(net, name, op), myGroup(0)
{
mySopFlags.setNeedGuide1(1);
}
SOP_Flatten::~SOP_Flatten() {}
unsigned
SOP_Flatten::disableParms()
{
unsigned changed = 0;
changed = enableParm(3, !DIRPOP());
changed += enableParm(4, DIRPOP());
return changed;
}
OP_ERROR
SOP_Flatten::cookInputGroups(OP_Context &context, int alone)
{
if (alone) if (lockInputs(context) >= UT_ERROR_ABORT) return error();
UT_String grp_name;
GU_Detail *pgdp = alone ? (GU_Detail *)inputGeo(0, context) : gdp;
myGroup = 0;
getGroups(grp_name);
if (grp_name.isstring())
{
myGroup = parsePointGroups((const char *)grp_name, pgdp);
if (!myGroup)
{
addError(SOP_ERR_BADGROUP, grp_name);
}
else if (!alone)
{
select(*const_cast<GA_PointGroup*>(myGroup), 1);
}
}
else if (!alone)
{
select(GU_SPoint);
}
checkInputChanged(0, -1, myDetailGroupPair, pgdp, myGroup);
if (alone)
{
destroyAdhocGroups();
unlockInputs();
}
return error();
}
OP_ERROR
SOP_Flatten::cookMySop(OP_Context &context)
{
GEO_Point *ppt;
fpreal now = context.getTime();
int plane;
float dist;
UT_Vector3 normal, p;
UT_Vector4 pos;
if (lockInputs(context) >= UT_ERROR_ABORT)
return error();
plane = 2;
duplicateSource(0, context);
setVariableOrder(3, 2, 0, 1);
setCurGdh(0, myGdpHandle);
setupLocalVars();
if (error() < UT_ERROR_ABORT && cookInputGroups(context) < UT_ERROR_ABORT)
{
UT_AutoInterrupt progress("Flattening Points");
GA_FOR_ALL_OPT_GROUP_POINTS(gdp, myGroup, ppt)
{
if (progress.wasInterrupted())
break;
myCurPtOff[0] = ppt->getMapOffset();
dist = DIST(now);
if (!DIRPOP())
{
switch (ORIENT())
{
case 0 :
normal.assign(0, 0, 1);
break;
case 1 :
normal.assign(1, 0, 0);
break;
case 2 :
normal.assign(0, 1, 0);
break;
}
}
else
{
normal.assign(NX(now), NY(now), NZ(now));
normal.normalize();
}
p.assign(ppt->getPos()(0), ppt->getPos()(1),
ppt->getPos()(2));
p -= normal * (dot(normal, p) - dist);
pos = ppt->getPos();
pos(0) = p.x();
pos(1) = p.y();
pos(2) = p.z();
ppt->setPos(pos);
}
}
unlockInputs();
resetLocalVarRefs();
return error();
}
OP_ERROR
SOP_Flatten::cookMyGuide1(OP_Context &context)
{
float now;
UT_BoundingBox bbox;
UT_Matrix3 mat3;
UT_Matrix4 xform;
float dist, nx = 0, ny = 0, nz = 1;
float cx, cy, cz;
float sx, sy, sz;
float size;
const int divs = 5;
UT_Vector3 zaxis(0, 0, 1);
if (lockInputs(context) >= UT_ERROR_ABORT) return error();
now = context.getTime();
myGuide1->clearAndDestroy();
dist = DIST(now);
if (!DIRPOP())
{
switch (ORIENT())
{
case 0 :
nx = 0; ny = 0; nz = 1;
break;
case 1 :
nx = 1; ny = 0; nz = 0;
break;
case 2 :
nx = 0; ny = 1; nz = 0;
break;
}
}
else
{
nx = NX(now); ny = NY(now); nz = NZ(now);
}
if (error() < UT_ERROR_ABORT)
{
UT_Vector3 normal(nx, ny, nz);
normal.normalize();
inputGeo(0, context)->getBBox(&bbox);
sx = bbox.sizeX();
sy = bbox.sizeY();
sz = bbox.sizeZ();
size = sqrtf(sx*sx + sy*sy + sz*sz);
cx = normal.x() * dist;
cy = normal.y() * dist;
cz = normal.z() * dist;
myGuide1->meshGrid(divs, divs, size, size);
mat3.dihedral(zaxis, normal);
xform = mat3;
xform.translate(cx, cy, cz);
myGuide1->transform(xform);
}
unlockInputs();
return error();
}
const char *
SOP_Flatten::inputLabel(unsigned) const
{
return "Geometry to Flatten";
}