HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SOP_Surface.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  * The Surface SOP. This SOP Surfaces the volume into polygons.
27  */
28 
29 #include "SOP_Surface.h"
30 
31 #include <SOP/SOP_Guide.h>
32 #include <GU/GU_Detail.h>
33 #include <GU/GU_Surfacer.h>
34 #include <GU/GU_PrimPoly.h>
35 #include <GU/GU_PrimVolume.h>
36 #include <OP/OP_AutoLockInputs.h>
37 #include <OP/OP_Operator.h>
38 #include <OP/OP_OperatorTable.h>
39 #include <PRM/PRM_Include.h>
40 #include <UT/UT_DSOVersion.h>
41 #include <UT/UT_VoxelArray.h>
42 
43 using namespace HDK_Sample;
44 
45 void
47 {
48  table->addOperator(new OP_Operator(
49  "hdk_surface",
50  "Surface",
53  1,
54  1,
55  0));
56 }
57 
58 static PRM_Name names[] = {
59  PRM_Name("iso", "Iso Value"),
60  PRM_Name("buildpolysoup","Build Polygon Soup"),
61 };
62 
65  PRM_Template(PRM_FLT, 1, &names[0], PRMzeroDefaults),
66  PRM_Template(PRM_TOGGLE, 1, &names[1], PRMzeroDefaults),
67  PRM_Template(),
68 };
69 
70 
71 OP_Node *
73 OP_Operator *op)
74 {
75  return new SOP_Surface(net, name, op);
76 }
77 
79  : SOP_Node(net, name, op)
80 {
81 }
82 
84 
87 {
88  fpreal t = context.getTime();
89 
90  // We must lock our inputs before we try to access their geometry.
91  // OP_AutoLockInputs will automatically unlock our inputs when we return.
92  // NOTE: Don't call unlockInputs yourself when using this!
93  OP_AutoLockInputs inputs(this);
94  if (inputs.lock(context) >= UT_ERROR_ABORT)
95  return error();
96 
97  const float iso = ISO(t);
98  const bool makepolysoup = BUILDPOLYSOUP(t);
99 
100  // Erase our gdp but keep it around for reuse
101  // This is the same as clearAndDestroy() in terms of the result
102  // but keeps a list of all the primitives around so that
103  // if you immediately recreate the same thing it can be done
104  // very fast.
105  gdp->stashAll();
106 
107  // Get first input
108  const GU_Detail *volgdp = inputGeo(0);
109 
110  const GEO_Primitive *prim = 0;
111  const GEO_PrimVolume *vol = 0;
112  if (volgdp->getNumPrimitives() > 0)
113  {
114  GA_Offset primoff = volgdp->primitiveOffset(GA_Index(0));
115  prim = volgdp->getGEOPrimitive(primoff);
116  if (prim->getTypeId() == GA_PRIMVOLUME)
117  vol = (const GEO_PrimVolume *)prim;
118  }
119 
120  if (vol)
121  {
123 
124  // This is only a rough approximation of the volume size.
125  // It does not take into account the rotation of the box.
126  UT_BoundingBox bbox;
127  vol->getBBox(&bbox);
128  UT_Vector3 pos = bbox.minvec();
129  UT_Vector3 size = bbox.size();
130  int rx, ry, rz;
131  vol->getRes(rx, ry, rz);
132 
133  GU_Surfacer surfacer(*gdp, pos, size, rx, ry, rz, makepolysoup);
134 
135  for (int z = 0; z < rz; z++)
136  {
137  for (int y = 0; y < ry; y++)
138  {
139  for (int x = 0; x < rx; x++)
140  {
141  bool isless = false;
142  bool ismore = false;
143 
144  // The surfacer wants the eight corner points
145  // of the cube to surface.
146  fpreal density[8];
147  for (int d = 0; d < 8; d++)
148  {
149  density[d] = vox->getValue(x + ((d>>0) & 1),
150  y + ((d>>1) & 1),
151  z + ((d>>2) & 1));
152  density[d] -= iso;
153  if (density[d] < 0.0)
154  isless = true;
155  else
156  ismore = true;
157  }
158  // We don't need to surface voxels that don't have
159  // a crossing point.
160  // If your data structure supports sparse volumes,
161  // this can be used to avoid even reading the values.
162  if (isless && ismore)
163  {
164  surfacer.addCell(x, y, z, density, 0);
165  }
166  }
167  }
168  }
169  }
170 
171  // free anything not reused
172  gdp->destroyStashed();
173 
174  return error();
175 }
176 
177 const char *
178 SOP_Surface::inputLabel(unsigned) const
179 {
180  return "Geometry to Surface";
181 }
void stashAll()
Definition: GA_Detail.h:138
virtual OP_ERROR error()
PRM_API const PRM_Type PRM_FLT
SOP_Surface(OP_Network *net, const char *name, OP_Operator *op)
Definition: SOP_Surface.C:78
bool getBBox(UT_BoundingBox *bbox) const override
OP_ERROR lock(OP_Context &context)
Locks all inputs.
fpreal getTime() const
Definition: OP_Context.h:62
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
UT_ErrorSeverity
Definition: UT_Error.h:25
SYS_FORCE_INLINE const GA_PrimitiveTypeId & getTypeId() const
Definition: GA_Primitive.h:177
GLint y
Definition: glcorearb.h:103
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
SYS_FORCE_INLINE GEO_Primitive * getGEOPrimitive(GA_Offset primoff)
Definition: GEO_Detail.h:1177
GA_Size GA_Offset
Definition: GA_Types.h:646
const GU_Detail * inputGeo(int index, OP_Context &)
Definition: SOP_Node.h:1150
static PRM_Template myTemplateList[]
Definition: SOP_Surface.h:42
GLuint const GLchar * name
Definition: glcorearb.h:786
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:640
GLint GLenum GLint x
Definition: glcorearb.h:409
GLenum GLenum GLsizei void * table
Definition: glad.h:5129
GLdouble t
Definition: glad.h:2397
GU_Detail * gdp
Definition: SOP_Node.h:1625
GLsizeiptr size
Definition: glcorearb.h:664
const char * inputLabel(unsigned idx) const override
Definition: SOP_Surface.C:178
fpreal64 fpreal
Definition: SYS_Types.h:277
void addCell(int x, int y, int z, const fpreal density[8], const UT_Vector3 gradient[8])
SYS_FORCE_INLINE GA_Offset primitiveOffset(GA_Index index) const
Given a primitive's index (in append order), return its data offset.
Definition: GA_Detail.h:419
static OP_Node * myConstructor(OP_Network *, const char *, OP_Operator *)
Definition: SOP_Surface.C:72
SYS_FORCE_INLINE GA_Size getNumPrimitives() const
Return the number of primitives.
Definition: GA_Detail.h:408
PRM_API const PRM_Type PRM_TOGGLE
void destroyStashed()
Definition: GA_Detail.h:156
void newSopOperator(OP_OperatorTable *table)
Definition: SOP_Surface.C:46
UT_VoxelArrayHandleF getVoxelHandle() const
PRM_API PRM_Default PRMzeroDefaults[]
OP_ERROR cookMySop(OP_Context &context) override
Method to cook geometry for the SOP.
Definition: SOP_Surface.C:86
void getRes(int &rx, int &ry, int &rz) const
Returns the resolution of the voxel array.