HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GEO_ImplicitSurface.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: GEO_ImplicitSurface.h
7  *
8  * COMMENTS: Compound implicit surface evaluation with recursive operations.
9  */
10 
11 #pragma once
12 
13 
14 #ifndef __GEO_ImplicitSurface_h__
15 #define __GEO_ImplicitSurface_h__
16 
17 #include "GEO_ImplicitSurfaceOp.h"
19 
20 #include <UT/UT_Vector.h>
21 #include <UT/UT_Tracing.h>
22 #include <UT/UT_BoundingBox.h>
23 #include <GA/GA_Handle.h>
24 #include <GA/GA_PrimVolumeXform.h>
25 #include <GEO/GEO_Detail.h>
26 
27 
28 //////////////////////////////////////////////////////////////////////////////
29 // GEO_ImplicitSurface
30 //////////////////////////////////////////////////////////////////////////////
31 
32 /// Compound Implicit Surface - evaluates compound SDFs built from basic shapes
33 /// combined with boolean/blending operations.
34 ///
35 /// Constructed from a GEO_Detail whose points carry implicit surface attributes.
36 /// The evaluation uses a recursive algorithm to handle nested Begin/End groups.
37 ///
38 /// Shape/operation sequence structure:
39 /// - Begin op: starts a new group (recursive call)
40 /// - End shape + Binary op: ends group, returns to caller who applies the op
41 /// - Unary op: modifies current SDF in place
42 /// - Binary op + regular shape: evaluates shape, combines with current SDF
43 template <VEX_Precision PREC>
45 {
46 public:
53 
54  /// Time derivatives of shape/operation parameters for computing dparm
55  struct DParms
56  {
57  /// Linear velocity (time derivative of position)
58  Vec3 v = {0, 0, 0};
59  /// Angular velocity in world space: vel(x) = cross(w, x - pos) + v
60  Vec3 w = {0, 0, 0};
61  /// Time derivative of shape parameters (e.g., change in box size)
62  Vec4 shape_dparms = {0, 0, 0, 0};
63  /// Time derivative of operation parameters (e.g., change in smooth k)
64  Vec4 op_dparms = {0, 0, 0, 0};
65  };
66 
69 
70  // Data members
74  int myNPoints = 0;
75 
76  GEO_ImplicitSurface() = default;
77 
78  /// Construct from geometry, reading all implicit surface attributes
79  /// from point data into the internal arrays.
81  {
82  utZoneScopedN("implicit surface - init");
83 
84  myNPoints = (int)geo.getNumPoints();
85  if (myNPoints == 0)
86  return;
87 
88  const GA_IndexMap &ptmap = geo.getPointMap();
89 
90  // Bind attribute handles
91  GA_ROHandleV3 h_P(&geo, GA_ATTRIB_POINT, "P");
92  GA_ROHandleM3 h_transform(&geo, GA_ATTRIB_POINT, "transform");
93 
94  GA_ROHandleS h_shape(&geo, GA_ATTRIB_POINT, "shape");
95  GA_ROHandleV4 h_shapevals(&geo, GA_ATTRIB_POINT, "shapevals");
96 
97  GA_ROHandleS h_op(&geo, GA_ATTRIB_POINT, "implicitsurface");
98  GA_ROHandleV4 h_opvals(&geo, GA_ATTRIB_POINT, "implicitsurfacevals");
99 
100  // Optional velocity attributes
101  GA_ROHandleV3 h_v(&geo, GA_ATTRIB_POINT, "v");
102  GA_ROHandleV3 h_w(&geo, GA_ATTRIB_POINT, "w");
103  GA_ROHandleV4 h_shapedvals(&geo, GA_ATTRIB_POINT, "shapedvals");
104  GA_ROHandleV4 h_opdvals(&geo, GA_ATTRIB_POINT, "implicitsurfacedvals");
105 
106  if (!h_shape.isValid() || !h_op.isValid())
107  {
108  myNPoints = 0;
109  return;
110  }
111 
112  myShapes.setSizeNoInit(myNPoints);
113  myOps.setSizeNoInit(myNPoints);
114  myDParms.setSizeNoInit(myNPoints);
115 
116  for (int i = 0; i < myNPoints; i++)
117  {
118  GA_Offset off = ptmap.offsetFromIndex(i);
119 
120  // Shape
122  if (h_transform.isValid())
123  xform = h_transform.get(off);
124  else
125  xform.identity();
126  myShapes[i] = Shape(h_shape.get(off),
127  h_P.isValid() ? Vec3(h_P.get(off)) : Vec3(0, 0, 0),
128  xform,
129  h_shapevals.isValid() ? Vec4(h_shapevals.get(off)) : Vec4(1, 1, 1, 0));
130 
131  // Op
132  myOps[i] = Op(h_op.get(off),
133  xform,
134  h_opvals.isValid() ? Vec4(h_opvals.get(off)) : Vec4(0, 0, 0, 0));
135 
136  // DParms
137  DParms &dp = myDParms[i];
138  dp.v = h_v.isValid() ? Vec3(h_v.get(off)) : Vec3(0, 0, 0);
139  dp.w = h_w.isValid() ? Vec3(h_w.get(off)) : Vec3(0, 0, 0);
140  dp.shape_dparms = h_shapedvals.isValid() ? Vec4(h_shapedvals.get(off)) : Vec4(0, 0, 0, 0);
141  dp.op_dparms = h_opdvals.isValid() ? Vec4(h_opdvals.get(off)) : Vec4(0, 0, 0, 0);
142  }
143  }
144 
145  // ========================================
146  // Transform
147  // ========================================
148 
149  /// Apply translation, rotation, and uniform scale to all shapes.
150  /// Positions: new_pos = rotate(old_pos * uniform_scale) + translate
151  /// Orientations: composed with the rotation quaternion
152  /// Distance parameters: scaled by uniform_scale on shapes and ops
153  /// NOTE: DParms (v, w) are not transformed by this method.
154  void applyTransform(const Vec3 &translate, const Quat &rotate,
155  Float uniform_scale)
156  {
157  VEXmat3<PREC> rot_mat;
158  rotate.getRotationMatrix(rot_mat);
159  for (int i = 0; i < myNPoints; i++)
160  {
161  myShapes[i].myPos = rotate.rotate(myShapes[i].myPos * uniform_scale)
162  + translate;
163  myShapes[i].myTransform = rot_mat * myShapes[i].myTransform;
164 
165  myShapes[i].scale(uniform_scale);
166  myOps[i].scale(uniform_scale);
167  }
168  }
169 
170  /// Transform the implicit surface from world space into the index space
171  /// of a VDB defined by the given GEO_PrimVolumeXform.
172  /// After this call, evaluating positions in index space will produce
173  /// SDF values in index-space units (multiply by voxelsize for world).
175  {
176  // Decompose world->index into translate, rotate, uniform_scale.
177  // toVoxelSpace(pos) - 0.5 = (pos - center) * myInverseXform * 0.5
178  UT_Matrix3D rot_mat(index_xform.myInverseXform);
179  UT_Vector3D scales;
180  rot_mat.extractScalesT(scales, (UT_Vector3D *)nullptr);
181  Float uniform_scale = Float(scales.x()) * Float(0.5);
182  Quat rotate;
183  rotate.updateFromRotationMatrix(rot_mat);
184  Vec3 center(index_xform.myCenter);
185  Vec3 translate = -rotate.rotate(center * uniform_scale);
186 
187  applyTransform(translate, rotate, uniform_scale);
188  }
189 
190  /// Apply offset to the surface
191  void applyOffset(const Float offset);
192 
193  // ========================================
194  // Evaluation methods
195  // ========================================
196 
197  Float operator()(const Vec3 &P) const;
198  Float operator()(const Vec3 &P, Vec3 &grad) const;
199  Float operator()(const Vec3 &P, Vec3 &grad, Float &dparm) const;
200 
201  // ========================================
202  // Batched evaluation (surfaces outer, points inner)
203  // ========================================
204 
205  void evalBatched(int npts, const Vec3 *P, Float *sdf) const;
206  void evalBatched(int npts, const Vec3 *P, Float *sdf, Vec3 *grad) const;
207  void evalBatched(int npts, const Vec3 *P, Float *sdf, Vec3 *grad,
208  Float *dparm) const;
209 
210  /// Same as above, but also outputs the winning shape id per point.
211  /// `grad`/`dparm` may be nullptr if not needed.
212  void evalBatched(int npts, const Vec3 *P, Float *sdf, int *shape_id,
213  Vec3 *grad, Float *dparm) const;
214 
215  /// Batched evaluation that also interpolates an arbitrary point
216  /// attribute (float or vector) across the blended shapes.
217  void evalBatchedAttr(int npts, const Vec3 *P, Float *sdf, int *shape_id,
218  Vec3 *grad, Float *dparm,
219  const GA_ROHandleF &h_attr, const GA_IndexMap &ptmap,
220  Float *attr_out) const;
221  void evalBatchedAttr(int npts, const Vec3 *P, Float *sdf, int *shape_id,
222  Vec3 *grad, Float *dparm,
223  const GA_ROHandleV3 &h_attr, const GA_IndexMap &ptmap,
224  Vec3 *attr_out) const;
225 
226  /// Batched evaluation that also blends the per-shape rigid velocity
227  /// (v + w x (P - pos)) across the blended shapes.
228  void evalBatchedVel(int npts, const Vec3 *P, Float *sdf, int *shape_id,
229  Vec3 *grad, Float *dparm, Vec3 *rigid_vel) const;
230 
231  // ========================================
232  // Interval evaluation (for spatial pruning)
233  // ========================================
234 
235  /// Evaluate SDF over an interval region, returning relevant shape IDs.
236  IntervalF evalInterval(const BBox3 &P, UT_Array<int> &relevant_ids) const;
237 
238  /// Evaluate SDF over an interval region
239  IntervalF evalInterval(const BBox3 &P) const;
240 
241  /// Evaluate SDF over an interval region
242  IntervalF evalInterval(const Vec3 &center, const Float radius) const;
243 
244  /// Evaluate interval over a sphere and build a pruned surface expression.
245  /// Pruning follows operation interval optimization flags and emits a new
246  /// shape/op sequence equivalent on the queried sphere.
248  const Vec3 &center,
249  const Float radius,
250  GEO_ImplicitSurface<PREC> &pruned) const;
251 
252  /// Return a conservative estimate on the isoline offset.
253  /// This is used whe we get bounding box based on the visualization geometry,
254  /// we expand this bounding box by this offset to get a better estimate
255  /// on a region where implicut surface is contained.
257  Float offset = 0.0;
258  for (auto& op : myOps)
259  {
261  {
262  offset += SYSabs(op.myParms[0]);
263  }
265  {
266  offset += SYSabs(op.myParms[0]) + SYSabs(op.myParms[1])/2;
267  }
268  }
269  return offset;
270  }
271 
272 private:
273  // ========================================
274  // Internal recursive evaluation helpers
275  // ========================================
276  // Not part of the public interface: these are implemented and
277  // implicitly instantiated only inside GEO_ImplicitSurface.C, so their
278  // definitions (and the lambda closure types some of them are called
279  // with) never need to be visible outside that translation unit.
280 
281  /// Recursive single-point evaluation of a shape/operation group.
282  /// Returns the index of the End that terminated the group, or
283  /// myNPoints if no End was found.
284  template <bool WantGrad, bool WantDParm>
285  int evalGroup(int start, const Vec3 &P, Float &sdf, int &shape_id,
286  Vec3 *grad, Float *dparm) const;
287 
288  /// Recursive batched evaluation of a shape/operation group. `valFn`
289  /// computes the interpolated `Val` contributed by shape `i` at point
290  /// P when WantInterp is true; ignored otherwise.
291  template <bool WantGrad, bool WantDParm, bool WantInterp,
292  typename Val, typename ValFn>
293  int evalGroupBatched(int start, int npts, const Vec3 *P, Float *sdf,
294  int *shape_id, Vec3 *grad, Float *dparm,
295  const ValFn &valFn, Val *interp_val) const;
296 
297  /// Recursive interval evaluation with relevant_ids pruning.
298  int evalGroupInterval(int start, const BBox3 &P, IntervalF &sdf,
299  UT_Array<int> &relevant_ids) const;
300 
301  /// Recursive interval evaluation over a bounding sphere.
302  int evalGroupIntervalSphere(int start, const Vec3 &center, Float radius,
303  IntervalF &sdf) const;
304 };
305 
306 #endif // __GEO_ImplicitSurface_h__
A class to manage an ordered array which has fixed offset handles.
Definition: GA_IndexMap.h:63
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
UT_IntervalT< Float > IntervalF
Definition: ImathVec.h:40
Axis-aligned bounding box (AABB).
Definition: GEO_Detail.h:41
const GLdouble * v
Definition: glcorearb.h:837
GLuint start
Definition: glcorearb.h:475
IntervalF evalInterval(const BBox3 &P, UT_Array< int > &relevant_ids) const
Evaluate SDF over an interval region, returning relevant shape IDs.
UT_BoundingBoxT< Float > BBox3
Vec4 op_dparms
Time derivative of operation parameters (e.g., change in smooth k)
SYS_FORCE_INLINE bool isValid() const
Definition: GA_Handle.h:948
SYS_FORCE_INLINE const HOLDER & get(GA_Offset off, int comp=0) const
Get the string at the given offset.
Definition: GA_Handle.h:953
Float operator()(const Vec3 &P) const
#define SYSabs(a)
Definition: SYS_Math.h:1954
GEO_ImplicitSurface(const GEO_Detail &geo)
void getRotationMatrix(UT_Matrix3 &mat) const
typename VEX_PrecisionResolver< P >::vec3_type VEXvec3
Definition: VEX_PodTypes.h:70
GA_Size GA_Offset
Definition: GA_Types.h:653
void applyTransform(const Vec3 &translate, const Quat &rotate, Float uniform_scale)
#define utZoneScopedN(name)
Definition: UT_Tracing.h:222
const GA_IndexMap & getPointMap() const
Definition: GA_Detail.h:753
GEO_ImplicitBasicSurface< PREC > Shape
Vec4 shape_dparms
Time derivative of shape parameters (e.g., change in box size)
GLintptr offset
Definition: glcorearb.h:665
IntervalF outputBoundAndPrune(const Vec3 &center, const Float radius, GEO_ImplicitSurface< PREC > &pruned) const
void evalBatchedAttr(int npts, const Vec3 *P, Float *sdf, int *shape_id, Vec3 *grad, Float *dparm, const GA_ROHandleF &h_attr, const GA_IndexMap &ptmap, Float *attr_out) const
typename VEX_PrecisionResolver< P >::float_type VEXfloat
Definition: VEX_PodTypes.h:67
void evalBatched(int npts, const Vec3 *P, Float *sdf) const
UT_ValArray< DParms > myDParms
void applyIndexSpaceTransform(const GA_PrimVolumeXform &index_xform)
UT_ValArray< Op > myOps
SYS_FORCE_INLINE T get(GA_Offset off, int comp=0) const
Definition: GA_Handle.h:210
ImageBuf OIIO_API rotate(const ImageBuf &src, float angle, string_view filtername=string_view(), float filterwidth=0.0f, bool recompute_roi=false, ROI roi={}, int nthreads=0)
SYS_FORCE_INLINE bool isValid() const
Definition: GA_Handle.h:194
UT_Vector4T< Float > Vec4
Quaternion class.
Definition: GEO_Detail.h:49
void evalBatchedVel(int npts, const Vec3 *P, Float *sdf, int *shape_id, Vec3 *grad, Float *dparm, Vec3 *rigid_vel) const
SYS_FORCE_INLINE GA_Offset offsetFromIndex(GA_Index ordered_index) const
Definition: GA_IndexMap.h:118
GU_API void xform(CE_Context &context, bool recompile, int npts, const cl::Buffer &outPos, const cl::Buffer &inPos, const cl::Buffer &surfacexform, const cl::Buffer *grp=nullptr)
GEO_ImplicitSurfaceOp< PREC > Op
void applyOffset(const Float offset)
Apply offset to the surface.
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
Time derivatives of shape/operation parameters for computing dparm.
PUGI__FN char_t * translate(char_t *buffer, const char_t *from, const char_t *to, size_t to_length)
Definition: pugixml.cpp:8574
UT_ValArray< Shape > myShapes
SYS_NO_DISCARD_RESULT UT_Vector3T< T > rotate(const UT_Vector3T< T > &) const
VEXfloat< PREC > Float
GEO_ImplicitSurface()=default
typename VEX_PrecisionResolver< P >::mat3_type VEXmat3
Definition: VEX_PodTypes.h:73
void extractScalesT(UT_Vector3T< S > &scales, UT_Vector3T< S > *shears)
void updateFromRotationMatrix(const UT_Matrix3 &)
SYS_FORCE_INLINE GA_Size getNumPoints() const
Return the number of points.
Definition: GA_Detail.h:343
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:665