HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_SurfaceDistance.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: GU_SurfaceDistance.h (GU Library, C++)
7  *
8  * COMMENTS:
9  * Approximates geodesic distance.
10  * This code is related to the soft falloff code in GEO_Transform, but is
11  * mostly a replacement for it as of Houdini 16.5.
12  */
13 
14 #ifndef __GU_SurfaceDistance_h__
15 #define __GU_SurfaceDistance_h__
16 
17 #include "GU_API.h"
18 
19 #include <GA/GA_Types.h>
20 #include <GA/GA_Handle.h>
21 #include <GEO/GEO_Detail.h>
22 #include <UT/UT_Map.h>
23 #include <UT/UT_PriorityQueue.h>
24 #include <UT/UT_Set.h>
25 
26 class SoftSymmetryParms;
27 
28 // keep this synced with the parameter in $PRM/PRM_Shared.C
30 {
36  GU_SOFT_METRIC_INVALID
37 };
38 
39 // This class contains all the data needed to efficiently compute surface
40 // distances. It will automatically invalidate cache items when inputs to the
41 // query are incompatible with the cached data. This can help SOPs that want
42 // to save time on repeated calls, typically due to small changes in the
43 // radius.
45 {
46  // set of points used to identify an edge, the offsets are always specified
47  // in ascending order
48  typedef std::pair<GA_Offset, GA_Offset> Edge;
49 
50  // describes distances and lead points for the specified edge
51  struct QueueEntry
52  {
53  QueueEntry(const Edge &e, fpreal len,
54  fpreal mindist, fpreal dist0, fpreal dist1,
55  GA_Offset src0, GA_Offset src1)
56  : myEdge(e)
57  , myEdgeLength(len)
58  , myMinDist(mindist)
59  , myDist0(dist0)
60  , myDist1(dist1)
61  , mySrc0(src0)
62  , mySrc1(src1)
63  , myPos(-1)
64  {}
65 
66  Edge myEdge;
67  fpreal myEdgeLength;
68  fpreal myMinDist; // distance to edge
69  fpreal myDist0; // distance to myEdge.first
70  fpreal myDist1; // distance to myEdge.second
71  GA_Offset mySrc0; // closest lead point to myEdge.first
72  GA_Offset mySrc1; // closest lead point to myEdge.second
73  unsigned int myPos; // position in the priority queue
74  };
75 
76  // order items in the priority queue so edges with smaller distance bounds
77  // are explored first
78  class QueueEntryCmp
79  {
80  public:
81  bool operator()(const QueueEntry *a, const QueueEntry *b) const
82  { return a->myMinDist > b->myMinDist; }
83  };
84 
85  class PriorityQueue :
86  public UT_PriorityQueue<QueueEntry *, QueueEntryCmp, true>
87  {
88  public:
89  virtual ~PriorityQueue() {}
90  virtual void changedPosition(QueueEntry *e, unsigned int idx) const
91  { e->myPos = idx; }
92  };
93 
94  // This is a utility class for traversing geometry. It will respect the
95  // side of the symmetry plane assigned in the constructor.
96  class Walker
97  {
98  public:
99  Walker(int side) : myRadius(-1), mySide(side) {}
100  ~Walker() { clear(); }
101 
102  void clear();
103 
104  // adds an edge to the graph where pt0 is the closest point
105  void insertEdge(GA_Offset pt0, GA_Offset pt1, fpreal dist,
106  GA_Offset src, const GA_ROHandleV3 &p_attrib,
107  const GEO_Detail::SoftSymmetryParms *symmetry);
108  // adds an edge to the graph where traversal across a primitive to
109  // pt0 and pt1 are possible
110  void insertEdge(const GEO_Detail &gdp, const QueueEntry &qe,
111  GA_Offset pt0, GA_Offset pt1,
112  const GA_ROHandleV3 &p_attrib,
113  const GEO_Detail::SoftSymmetryParms *symmetry);
114 
115  // returns true if all edges have been traversed
116  bool isEmpty(fpreal radius) const
117  { return myQueue.isEmpty() || myRadius > radius; }
118 
119  // returns next edge to traverse and marks it as visited
120  QueueEntry *pop()
121  {
122  QueueEntry *qe = myQueue.head();
123  myQueue.remove(0);
124  qe->myPos = -1;
125 
126  myRadius = qe->myMinDist;
127  return qe;
128  }
129 
130  private:
131  // returns true if the edge has already been visited
132  bool isVisited(GA_Offset pt0, GA_Offset pt1) const;
133  void insertEdge(GA_Offset pt0, GA_Offset pt1, fpreal len,
134  fpreal dist, fpreal dist0, fpreal dist1,
135  GA_Offset src0, GA_Offset src1);
136 
137  // set of all discovered edges (including visited ones)
139  // queue of edges needing to be visited
140  PriorityQueue myQueue;
141  // all points closer than this radius have already been discovered
142  fpreal myRadius;
143  // side of the symmetry plane being respected
144  int mySide;
145  };
146 
147 public:
148  GU_SurfaceDistanceCache() { clear(); }
150 
151  void clear();
152 
153  // utility method to support multithreading of the surfdist VEX function
154  bool canReuse(const GEO_Detail &gdp, fpreal radius,
155  GU_SoftDistanceMetric metric) const;
156 
157  // group of points with valid distances (and lead points)
159  { return myAffectedGroup.get(); }
160 
161  // handle to detached attribute describing measured distances
163  { return GA_ROHandleF(myDistances.get()); }
164 
165  // handle to detached attribute describing closest lead point
167  { return GA_ROHandleID(mySourcePoints.get()); }
168 
169  // compute distances for points within the radius
170  void updateDistances(const GEO_Detail &gdp,
171  const GA_Group *srcgroup,
172  fpreal radius,
173  GU_SoftDistanceMetric metric,
174  const char *p_attr = "P",
175  const GEO_Detail::SoftSymmetryParms *symmetry = nullptr,
176  const GEO_Rolloff *rolloff = nullptr);
177 
178 private:
179  // invalidate cache if needed
180  void clearIfChanged(const GEO_Detail &gdp,
181  const GA_PointGroup *srcgroup,
182  fpreal radius,
183  GU_SoftDistanceMetric metric,
184  const GA_ROHandleV3 &p_attrib,
185  const GEO_Detail::SoftSymmetryParms *symmetry);
186 
187  void getAdjacentBoundaryVertices(GA_OffsetArray &verts,
188  const GEO_Detail &gdp, GA_Offset vtx);
189 
190  void getFaceVertices(UT_Array<GA_OffsetArray> &verts, const GEO_Detail &gdp,
191  GA_Offset vtx0, GA_Offset vtx1);
192 
193  void updateSurfAndEdgeDistances(const GEO_Detail &gdp,
194  const GA_PointGroup *srcgroup,
195  fpreal radius,
196  GU_SoftDistanceMetric metric,
197  const GA_ROHandleV3 &p_attrib,
198  const GEO_Detail::SoftSymmetryParms *symmetry);
199 
200  UT_SortedMap<int, Walker *> myWalkers;
201  // we convert hulls and polysoups to a polygon cage representation for
202  // efficiently measuring surface distances
203  GA_OffsetArray myVertices;
204  UT_Array<exint> myPolygons;
206  UT_Set<exint> myCurves;
207 
208  // set of points with computed distances (and lead points)
209  UT_UniquePtr<GA_PointGroup> myAffectedGroup;
210  // distance to the closest point in the input group
211  UT_UniquePtr<GA_Attribute> myDistances;
212  // the point in the input group that the current point is closest to
213  UT_UniquePtr<GA_Attribute> mySourcePoints;
214 
215  // values used to determine when to invalidate cached data
216  GU_SoftDistanceMetric myMetric;
217  fpreal myRadius;
218  exint myGdpId;
219  exint myGdpPrimitiveId;
220  exint myGdpTopologyId;
221 
222  bool myHasSymmetryParms;
223  bool myHasPtGroup;
224  GEO_Detail::SoftSymmetryParms mySymmetryParms;
225  UT_String myPAttrib;
226  GA_OffsetArray myPts;
227 };
228 
229 #endif
enum GU_API GU_SoftDistanceMetric
GA_ROHandleF getDistances() const
GA_API const UT_StringHolder dist
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
const GA_PointGroup * getAffectedGroup() const
GA_ROHandleT< int64 > GA_ROHandleID
Definition: GA_Handle.h:1242
GU_SOFT_CUSTOM
GU_SOFT_DISTANCE_ALONG_CONNECTED_EDGES
GA_Size GA_Offset
Definition: GA_Types.h:617
int64 exint
Definition: SYS_Types.h:116
GA_ROHandleID getSourcePoints() const
GA_ROHandleT< fpreal32 > GA_ROHandleF
Definition: GA_Handle.h:1212
GU_SOFT_GLOBAL_DISTANCE_WITH_CONNECTIVITY
#define GU_API
Definition: GU_API.h:12
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
GU_SOFT_SURFACE_DISTANCE
double fpreal
Definition: SYS_Types.h:270
GU_SOFT_GLOBAL_DISTANCE
GLenum src
Definition: glcorearb.h:1792