29 #include "SOP_VolumeProject.proto.h"
43 using namespace UT::Literal;
44 using namespace HDK_Sample;
51 SOP_VolumeProject::myConstructor,
52 SOP_VolumeProject::buildTemplates(),
57 static const char *theDsFile = R
"THEDSFILE(
62 label "Velocity Volumes"
65 parmtag { "script_action" "import soputils\nkwargs['geometrytype'] = (hou.geometryType.Primitives,)\nkwargs['inputindex'] = 0\nsoputils.selectGroupParm(kwargs)" }
66 parmtag { "script_action_help" "Select geometry from an available viewport.\nShift-click to turn on Select Groups." }
67 parmtag { "script_action_icon" "BUTTONS_reselect" }
72 label "Divergence Volume"
75 parmtag { "script_action" "import soputils\nkwargs['geometrytype'] = (hou.geometryType.Primitives,)\nkwargs['inputindex'] = 1\nsoputils.selectGroupParm(kwargs)" }
76 parmtag { "script_action_help" "Select geometry from an available viewport.\nShift-click to turn on Select Groups." }
77 parmtag { "script_action_icon" "BUTTONS_reselect" }
85 parmtag { "script_action" "import soputils\nkwargs['geometrytype'] = (hou.geometryType.Primitives,)\nkwargs['inputindex'] = 2\nsoputils.selectGroupParm(kwargs)" }
86 parmtag { "script_action_help" "Select geometry from an available viewport.\nShift-click to turn on Select Groups." }
87 parmtag { "script_action_icon" "BUTTONS_reselect" }
95 parmtag { "script_action" "import soputils\nkwargs['geometrytype'] = (hou.geometryType.Primitives,)\nkwargs['inputindex'] = 3\nsoputils.selectGroupParm(kwargs)" }
96 parmtag { "script_action_help" "Select geometry from an available viewport.\nShift-click to turn on Select Groups." }
97 parmtag { "script_action_icon" "BUTTONS_reselect" }
122 label "LUT Round Pattern"
151 label "Zero Inactive"
160 SOP_VolumeProject::buildTemplates()
206 virtual void cook(
const CookParms &cookparms)
const;
215 return theSOPVolumeProjectVerb.get();
226 auto &&sopparms = cookparms.
parms<SOP_VolumeProjectParms>();
227 bool doround = sopparms.getLUTRound();
233 if (sopparms.getLUTCenter() - sopparms.getLUTRad() < 0)
243 if (sopparms.getLUTCenter() - sopparms.getLUTRad() < 0)
258 float lutmagic = sopparms.getLUTMagic();
260 lutmagic /= voxelsize.
x();
266 exint curtile =
r.begin();
272 int rad = sopparms.getLUTRad();
276 if (active->
getValue(vit.
x(), vit.
y(), vit.
z()) < 0.5)
278 if (sopparms.getZeroInactive())
289 if ( (vit.
z() - rad) & 1 )
291 if ( !( (vit.
z() + rad) & 1 ) )
295 for (
int z = radzmin;
z <= radzmax;
z++)
299 if (vit.
z() +
z >= divzres)
307 if ( (vit.
y() - rad) & 1 )
309 if ( !( (vit.
y() + rad) & 1 ) )
313 for (
int y = radymin;
y <= radymax;
y++)
317 if (vit.
y() +
y >= divyres)
325 if ( (vit.
x() - rad) & 1 )
327 if ( !( (vit.
x() + rad) & 1 ) )
331 for (
int x = radxmin;
x <= radxmax;
x++)
335 if (vit.
x() +
x >= divxres)
339 float val = (*div)(vit.
x()+
x, vit.
y()+
y, vit.
z()+
z);
342 val *= (*lut)(sopparms.getLUTCenter() -
x,
343 sopparms.getLUTCenter() -
y,
344 sopparms.getLUTCenter() -
z);
399 exint curtile =
r.begin();
409 for (
int dz = 0; dz <= 1; dz++)
411 int z = vit.
z() * 2 + dz;
414 for (
int dy = 0; dy <= 1; dy++)
416 int y = vit.
y() * 2 + dy;
419 for (
int dx = 0; dx <= 1; dx++)
421 int x = vit.
x() * 2 + dx;
425 float div_v = (*div_vox)(
x,
y,
z);
461 old_pos = pos_mip.
last();
462 old_neg = neg_mip.
last();
474 pos = pos_mip.
last();
475 neg = neg_mip.
last();
491 for (
int dz = 0; dz <= 1; dz++)
493 int z = vit.
z() * 2 + dz;
496 for (
int dy = 0; dy <= 1; dy++)
498 int y = vit.
y() * 2 + dy;
501 for (
int dx = 0; dx <= 1; dx++)
503 int x = vit.
x() * 2 + dx;
510 pos_v += (*old_pos)(
x,
y,
z);
511 neg_v += (*old_neg)(
x,
y,
z);
533 auto &&sopparms = cookparms.
parms<SOP_VolumeProjectParms>();
540 float mipmagic = sopparms.getMIPMagic();
541 mipmagic = 1 / mipmagic;
546 mipmagic *= voxelsize.
x();
547 mipmagic /= 4 *
M_PI;
552 exint curtile =
r.begin();
559 if (active->
getValue(vit.
x(), vit.
y(), vit.
z()) < 0.5)
567 bool inspect =
false;
580 minvalid.
x() = vit.
x() - sopparms.getLUTRad();
581 maxvalid.
x() = vit.
x() + sopparms.getLUTRad();
582 minvalid.
y() = vit.
y() - sopparms.getLUTRad();
583 maxvalid.
y() = vit.
y() + sopparms.getLUTRad();
584 minvalid.
z() = vit.
z() - sopparms.getLUTRad();
585 maxvalid.
z() = vit.
z() + sopparms.getLUTRad();
606 for (
int pass = 0; pass < pos_mip.
entries(); pass++)
608 auto && pos = pos_mip(pass);
609 auto && neg = neg_mip(pass);
626 mingoal.
x() = (vit.
x() >> (pass+2)) - 1;
627 mingoal.
y() = (vit.
y() >> (pass+2)) - 1;
628 mingoal.
z() = (vit.
z() >> (pass+2)) - 1;
629 maxgoal.
x() = (vit.
x() >> (pass+2)) + 1;
630 maxgoal.
y() = (vit.
y() >> (pass+2)) + 1;
631 maxgoal.
z() = (vit.
z() >> (pass+2)) + 1;
641 mingoal.
x() =
SYSmax(mingoal.
x(), 0);
642 mingoal.
y() =
SYSmax(mingoal.
y(), 0);
643 mingoal.
z() =
SYSmax(mingoal.
z(), 0);
644 maxgoal.
x() =
SYSmin(maxgoal.
x(), pos->getXRes()-1);
645 maxgoal.
y() =
SYSmin(maxgoal.
y(), pos->getYRes()-1);
646 maxgoal.
z() =
SYSmin(maxgoal.
z(), pos->getZRes()-1);
649 if (pass == pos_mip.
entries()-1)
654 maxgoal.
x() = pos->getXRes()-1;
655 maxgoal.
y() = pos->getYRes()-1;
656 maxgoal.
z() = pos->getZRes()-1;
663 for (
int z = mingoal.
z();
z <= maxgoal.
z();
z++)
665 bool ztest = (
z >= minvalid.
z() &&
z <= maxvalid.
z());
667 for (
int y = mingoal.
y();
y <= maxgoal.
y();
y++)
669 bool ytest = (
y >= minvalid.
y() &&
y <= maxvalid.
y());
670 for (
int x = mingoal.
x();
x <= maxgoal.
x();
x++)
672 bool xtest = (
x >= minvalid.
x() &&
x <= maxvalid.
x());
674 if (ztest && ytest && xtest)
697 float displen = p.
length();
698 float paxis = p(axis);
702 paxis /= (displen*displen*displen);
706 delta += pos_v.
w() * paxis;
721 float displen = p.
length();
722 float paxis = p(axis);
726 paxis /= (displen*displen*displen);
730 delta -= neg_v.
w() * paxis;
767 auto &&sopparms = cookparms.
parms<SOP_VolumeProjectParms>();
771 float mipmagic = sopparms.getMIPMagic();
772 mipmagic = 1 / mipmagic;
782 mipmagic *= voxelsize.
x();
785 mipmagic /= 4 *
M_PI;
793 exint curtile =
r.begin();
800 if (active->
getValue(vit.
x(), vit.
y(), vit.
z()) < 0.5)
808 bool inspect =
false;
821 minvalid.
x() = vit.
x() - sopparms.getLUTRad();
822 maxvalid.
x() = vit.
x() + sopparms.getLUTRad();
823 minvalid.
y() = vit.
y() - sopparms.getLUTRad();
824 maxvalid.
y() = vit.
y() + sopparms.getLUTRad();
825 minvalid.
z() = vit.
z() - sopparms.getLUTRad();
826 maxvalid.
z() = vit.
z() + sopparms.getLUTRad();
847 for (
int pass = 0; pass < pos_mip.
entries(); pass++)
849 auto && pos = pos_mip(pass);
850 auto && neg = neg_mip(pass);
867 mingoal.
x() = (vit.
x() >> (pass+2)) - 1;
868 mingoal.
y() = (vit.
y() >> (pass+2)) - 1;
869 mingoal.
z() = (vit.
z() >> (pass+2)) - 1;
870 maxgoal.
x() = (vit.
x() >> (pass+2));
871 maxgoal.
y() = (vit.
y() >> (pass+2));
872 maxgoal.
z() = (vit.
z() >> (pass+2));
873 if ( (vit.
x() >> (pass+1)) & 1)
879 if ( (vit.
y() >> (pass+1)) & 1)
885 if ( (vit.
z() >> (pass+1)) & 1)
900 mingoal.
x() =
SYSmax(mingoal.
x(), 0);
901 mingoal.
y() =
SYSmax(mingoal.
y(), 0);
902 mingoal.
z() =
SYSmax(mingoal.
z(), 0);
903 maxgoal.
x() =
SYSmin(maxgoal.
x(), pos->getXRes()-1);
904 maxgoal.
y() =
SYSmin(maxgoal.
y(), pos->getYRes()-1);
905 maxgoal.
z() =
SYSmin(maxgoal.
z(), pos->getZRes()-1);
908 if (pass == pos_mip.
entries()-1)
913 maxgoal.
x() = pos->getXRes()-1;
914 maxgoal.
y() = pos->getYRes()-1;
915 maxgoal.
z() = pos->getZRes()-1;
922 for (
int z = mingoal.
z();
z <= maxgoal.
z();
z++)
924 bool ztest = (
z >= minvalid.
z() &&
z <= maxvalid.
z());
926 for (
int y = mingoal.
y(); y <= maxgoal.
y(); y++)
928 bool ytest = (y >= minvalid.
y() && y <= maxvalid.
y());
929 for (
int x = mingoal.
x(); x <= maxgoal.
x(); x++)
931 bool xtest = (x >= minvalid.
x() && x <= maxvalid.
x());
933 if (ztest && ytest && xtest)
956 float displen = p.
length();
957 float paxis = p(axis);
961 paxis /= (displen*displen*displen);
965 delta += pos_v.
w() * paxis;
980 float displen = p.
length();
981 float paxis = p(axis);
985 paxis /= (displen*displen*displen);
989 delta -= neg_v.
w() * paxis;
1022 auto &&sopparms = cookparms.
parms<SOP_VolumeProjectParms>();
1036 if (sopparms.getGroup().isstring())
1048 notifyGroupParmListeners(cookparms.
getNode(), 0, -1, gdp, velgrp);
1052 if (sopparms.getDivGroup().isstring())
1066 if (sopparms.getLUTGroup().isstring())
1080 if (sopparms.getActiveGroup().isstring())
1118 cookparms.
sopAddWarning(
SOP_MESSAGE,
"Unmatched veloicty volume ignored; provide matching triples of velocity volumes.");
1162 cookparms.
sopAddWarning(
SOP_MESSAGE,
"Unmatched sets of velocity and divergence volumes specified. Unmatched ignored.");
1168 cookparms.
sopAddError(
SOP_MESSAGE,
"Unmatched sets of divergence and active volumes specified. Abandoning.");
1175 for (
int pass = 0; pass < npass; pass++)
1191 if (pass < active.
size())
1193 activeh =
active(pass)->getVoxelHandle();
1194 activev = &*activeh;
1198 sop_applyVelLUT(cookparms, &*vxh, &*divh, activev, &*lutxh, velx(pass)->getVoxelSize());
1199 sop_applyVelLUT(cookparms, &*vyh, &*divh, activev, &*lutyh, vely(pass)->getVoxelSize());
1200 sop_applyVelLUT(cookparms, &*vzh, &*divh, activev, &*lutzh, velz(pass)->getVoxelSize());
1202 if (sopparms.getDoMIP())
1206 sop_buildMipMap(pos_mip, neg_mip,
div(pass));
1208 if (sopparms.getMipBy4())
1210 sop_applyMipMap4(cookparms, 0,
1211 velx(pass), &*vxh, activev,
1213 sop_applyMipMap4(cookparms, 1,
1214 vely(pass), &*vyh, activev,
1216 sop_applyMipMap4(cookparms, 2,
1217 velz(pass), &*vzh, activev,
1222 sop_applyMipMap(cookparms, 0,
1223 velx(pass), &*vxh, activev,
1225 sop_applyMipMap(cookparms, 1,
1226 vely(pass), &*vyh, activev,
1228 sop_applyMipMap(cookparms, 2,
1229 velz(pass), &*vzh, activev,
1233 for (
auto && map : pos_mip)
1235 for (
auto && map : neg_mip)
1239 gdp->bumpAllDataIds();
static PRM_ChoiceList primGroupMenu
int x() const
Retrieve the current location of the iterator.
GA_API const UT_StringHolder div
SOP_Node * getNode() const
#define UTdebugPrintCd(...)
bool atEnd() const
Returns true if we have iterated over all of the voxels.
void setChoiceListPtr(const UT_StringRef &name, PRM_ChoiceList *list)
UT_ErrorSeverity sopAddWarning(int code, const char *msg=0, const UT_SourceLocation *loc=0) const
GOP_GroupParse::GroupCreator GroupCreator
void setValue(UT_Vector3I index, T value)
virtual ~SOP_VolumeProjectVerb()
constexpr SYS_FORCE_INLINE T & y() noexcept
void UTparallelForEachNumber(IntType nitems, const Body &body, const bool force_use_task_scope=true)
UT_Vector3T< float > UT_Vector3
GLdouble GLdouble GLdouble z
constexpr SYS_FORCE_INLINE T & z() noexcept
SYS_FORCE_INLINE const GA_PrimitiveTypeId & getTypeId() const
UT_VoxelArray< UT_Vector4 > UT_VoxelArrayV4
GEO_PrimVolumeXform getIndexSpaceTransform() const
constexpr SYS_FORCE_INLINE T length() const noexcept
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
bool atEnd() const
Returns true if we have iterated over all of the voxels.
void size(int xres, int yres, int zres, bool reset=true)
#define GA_FOR_ALL_OPT_GROUP_PRIMITIVES(gdp, grp, prim)
constexpr SYS_FORCE_INLINE T & x() noexcept
UT_ErrorSeverity sopAddError(int code, const char *msg=0, const UT_SourceLocation *loc=0) const
void rewind()
Resets the iterator to point to the first voxel.
const SOP_NodeVerb * cookVerb() const overridefinal
virtual CookMode cookMode(const SOP_NodeParms *parms) const
int opInterrupt(int percent=-1)
Constructs a PRM_Template list from an embedded .ds file or an istream.
void advance()
Advances the iterator to point to the next voxel.
void setValue(T t) const
Sets the voxel we are currently pointing to the given value.
void rewind()
Resets the iterator to point to the first voxel.
constexpr SYS_FORCE_INLINE T & z() noexcept
PRM_Template * templates() const
const GA_PrimitiveGroup * parsePrimitiveGroups(const char *pat, const GroupCreator &creator, bool numok=true, bool ordered=false, bool strict=false, GA_Index prim_offset=GA_Index(0), ParseInfo *info=0)
OP_ERROR cookMyselfAsVerb(OP_Context &context)
void selectInputGroup(const GA_Group *group, GA_GroupType grouptype) const
GLuint const GLchar * name
GLenum GLenum GLsizei void * table
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate active
void newSopOperator(OP_OperatorTable *table)
exint entries() const
Alias of size(). size() is preferred.
void setLinearTile(exint lineartilenum, UT_VoxelArray< T > *array)
T getValue(int x, int y, int z) const
virtual SOP_NodeParms * allocParms() const
UT_API UT_Interrupt * UTgetInterrupt()
Obtain global UT_Interrupt singleton.
constexpr SYS_FORCE_INLINE T & w() noexcept
const GU_Detail * inputGeo(exint idx) const
UT_Vector3 getVoxelSize() const
Returns the length of the voxel when you take an x, y, and z step.
OP_ERROR cookMySop(OP_Context &context) overridefinal
virtual UT_StringHolder name() const
UT_VoxelArrayHandleF getVoxelHandle() const
constexpr SYS_FORCE_INLINE T & y() noexcept
~SOP_VolumeProject() override
GU_DetailHandle & gdh() const
The initial state of gdh depends on the cookMode()
virtual void cook(const CookParms &cookparms) const
Compute the output geometry.
void advance()
Advances the iterator to point to the next voxel.
constexpr SYS_FORCE_INLINE T & x() noexcept