HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SOP_NURBS.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 NURBS SOP
27  */
28 
29 #include "SOP_NURBS.h"
30 #include <GU/GU_Detail.h>
31 #include <GU/GU_PrimNURBSurf.h>
32 #include <OP/OP_Operator.h>
33 #include <OP/OP_OperatorTable.h>
34 #include <PRM/PRM_Include.h>
35 #include <UT/UT_DSOVersion.h>
36 #include <SYS/SYS_Math.h>
37 #include <limits.h>
38 #include <stddef.h>
39 
40 using namespace HDK_Sample;
41 
42 ///
43 /// newSopOperator is the hook that Houdini grabs from this dll
44 /// and invokes to register the SOP. In this case we add ourselves
45 /// to the specified operator table.
46 ///
47 void
49 {
50  table->addOperator(new OP_Operator(
51  "hdk_nurbs", // Internal name
52  "NURBS", // UI name
53  SOP_NURBS::myConstructor, // How to build the SOP
54  SOP_NURBS::myTemplateList, // My parameters
55  0, // Min # of sources
56  0, // Max # of sources
57  0, // Local variables
58  OP_FLAG_GENERATOR)); // Flag it as generator
59 }
60 
63  PRM_Template(PRM_INT, // Integer parameter.
64  PRM_Template::PRM_EXPORT_TBX, // Export to top of viewer
67  PRM_Template::PRM_EXPORT_TBX, // Export to top of viewer
69  NULL, &PRMorderRange),
70  PRM_Template()
71 };
72 
73 OP_Node *
75 {
76  return new SOP_NURBS(net, name, op);
77 }
78 
80  : SOP_Node(net, name, op)
81 {
82  // This indicates that this SOP manually manages its data IDs,
83  // so that Houdini can identify what attributes may have changed,
84  // e.g. to reduce work for the viewport, or other SOPs that
85  // check whether data IDs have changed.
86  // By default, (i.e. if this line weren't here), all data IDs
87  // would be bumped after the SOP cook, to indicate that
88  // everything might have changed.
89  // If some data IDs don't get bumped properly, the viewport
90  // may not update, or SOPs that check data IDs
91  // may not cook correctly, so be *very* careful!
93 }
94 
96 
99 {
100  fpreal now = context.getTime();
101 
102  int nu = SYSmax(COLS(now), 2); // Number of columns
103  int nv = SYSmax(ROWS(now), 2); // Number of rows
104  int uorder = SYSmin(UORDER(now), nu);
105  int vorder = SYSmin(VORDER(now), nv);
106 
107  if (gdp->getNumPrimitives() == 1)
108  {
109  // NOTE: This SOP only ever generates a GEO_PrimNURBSurf,
110  // so we don't strictly *need* to check that it is
111  // one if the detail wasn't cleared, but it's best
112  // to check, just in case.
114  if (prim->getTypeId() == GA_PRIMNURBSURF)
115  {
116  GEO_PrimNURBSurf *surf = (GEO_PrimNURBSurf *)prim;
117  if (surf->getNumRows() != nv || surf->getNumCols() != nu)
118  {
119  // Just delete and start over if wrong rows/cols.
120  surf = NULL;
121  }
122  if (surf && surf->getUOrder() != uorder)
123  {
124  // Just
125  GA_NUBBasis *basis = new GA_NUBBasis(0, 1, nu+uorder, uorder, true);
126  if (surf->setUBasis(basis) != 0)
127  {
128  delete basis;
129  surf = NULL;
130  }
131  else
132  {
133  // We successfully modified a primitive, so we must
134  // bump the primitive list data ID.
136  }
137  }
138  if (surf && surf->getVOrder() != vorder)
139  {
140  GA_NUBBasis *basis = new GA_NUBBasis(0, 1, nv+vorder, vorder, true);
141  if (surf->setVBasis(basis) != 0)
142  {
143  delete basis;
144  surf = NULL;
145  }
146  else
147  {
148  // We successfully modified a primitive, so we must
149  // bump the primitive list data ID.
151  }
152  }
153  if (surf)
154  {
155  // Nothing to more do for existing NURBS surface.
156  return error();
157  }
158  }
159  }
160 
161  // In addition to destroying everything except the empty P
162  // and topology attributes, this bumps the data IDs for
163  // those remaining attributes, as well as the primitive list
164  // data ID.
165  gdp->clearAndDestroy();
166 
167  // Create a NURBS surface.
168  GEO_PrimNURBSurf *surf = GU_PrimNURBSurf::build(gdp, nv, nu, uorder, vorder);
169 
170  /// @see GEO_TPSurf for basis access methods.
171 
172  for (int u = 0; u < nu; u++)
173  {
174  fpreal s = SYSfit((fpreal)u, u, (fpreal)nu-1, 0, 1);
175  for (int v = 0; v < nv; v++)
176  {
177  fpreal t = SYSfit((fpreal)v, v, (fpreal)nv-1, 0, 1);
178 
179  UT_Vector4 P(s, 0, t, 1);
180  GA_Offset ptoff = surf->getPointOffset(v, u); // row, column
181  gdp->setPos4(ptoff, P);
182  }
183  }
184 
185  // We don't need to bump any data IDs here, because they were already
186  // bumped in clearAndDestroy().
187 
188  return error();
189 }
#define SYSmax(a, b)
Definition: SYS_Math.h:1538
PRM_API PRM_Name PRMorderName
int setUBasis(GA_Basis *ub)
Definition: GEO_TPSurf.h:366
GA_Primitive * getPrimitiveByIndex(GA_Index prim_idx)
Definition: GA_Detail.h:438
virtual OP_ERROR error()
int setVBasis(GA_Basis *vb)
Definition: GEO_TPSurf.h:375
const GLdouble * v
Definition: glcorearb.h:837
fpreal getTime() const
Definition: OP_Context.h:62
void clearAndDestroy()
Clear all the points/primitives out of this detail.
Definition: GEO_Detail.h:267
static OP_Node * myConstructor(OP_Network *, const char *, OP_Operator *)
Definition: SOP_NURBS.C:74
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint vorder
Definition: glad.h:2682
#define OP_FLAG_GENERATOR
Definition: OP_Operator.h:82
GLdouble s
Definition: glad.h:3009
UT_ErrorSeverity
Definition: UT_Error.h:25
SYS_FORCE_INLINE const GA_PrimitiveTypeId & getTypeId() const
Definition: GA_Primitive.h:177
SYS_FORCE_INLINE GA_Offset getPointOffset(unsigned int r, unsigned int c) const
Definition: GEO_Hull.h:435
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
unsigned getVOrder() const
Definition: GEO_TPSurf.h:389
PRM_API const PRM_Type PRM_INT
GA_Size GA_Offset
Definition: GA_Types.h:641
void setPos4(GA_Offset ptoff, const UT_Vector4 &pos)
Set P from a UT_Vector4.
Definition: GA_Detail.h:302
void bumpDataId()
Use this to mark primitives or their intrinsic data as dirty.
SYS_FORCE_INLINE int getNumRows() const
Definition: GEO_Hull.h:368
NURBS basis classes which maintain knot vectors.
Definition: GA_NUBBasis.h:44
SOP_NodeFlags mySopFlags
Definition: SOP_Node.h:1625
GLuint const GLchar * name
Definition: glcorearb.h:786
GLenum GLenum GLsizei void * table
Definition: glad.h:5129
void setManagesDataIDs(bool onOff)
Definition: SOP_NodeFlags.h:36
GLdouble t
Definition: glad.h:2397
GU_Detail * gdp
Definition: SOP_Node.h:1622
static PRM_Template myTemplateList[]
Definition: SOP_NURBS.h:43
fpreal64 fpreal
Definition: SYS_Types.h:277
OP_ERROR cookMySop(OP_Context &context) override
cookMySop does the actual work of the SOP computing
Definition: SOP_NURBS.C:98
SYS_FORCE_INLINE GA_Size getNumPrimitives() const
Return the number of primitives.
Definition: GA_Detail.h:408
static GU_PrimNURBSurf * build(GEO_Detail *gudp, int rows, int cols, int orderu=4, int orderv=4, int wrapu=0, int wrapv=0, int interpEndsU=1, int interpEndsV=1, GEO_SurfaceType type=GEO_PATCH_QUADS, int appendPoints=1)
SOP_NURBS(OP_Network *net, const char *name, OP_Operator *op)
Definition: SOP_NURBS.C:79
const GA_PrimitiveList & getPrimitiveList() const
Definition: GA_Detail.h:792
void newSopOperator(OP_OperatorTable *table)
Definition: SOP_NURBS.C:48
SYS_FORCE_INLINE int getNumCols() const
Definition: GEO_Hull.h:375
PRM_API PRM_Name PRMdivName
PRM_API PRM_Default PRMfourDefaults[]
unsigned getUOrder() const
Definition: GEO_TPSurf.h:388
~SOP_NURBS() override
Definition: SOP_NURBS.C:95
PRM_API PRM_Range PRMorderRange
#define SYSmin(a, b)
Definition: SYS_Math.h:1539
GLdouble GLdouble GLint GLint uorder
Definition: glad.h:2682