HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_AttributeRefMap.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: GA_AttributeRefMap.h ( GA Library, C++)
7  *
8  * COMMENTS: A mapping between destination and source attributes for
9  * various operations manipulating multiple attributes.
10  */
11 
12 #ifndef __GA_AttributeRefMap__
13 #define __GA_AttributeRefMap__
14 
15 #include "GA_API.h"
16 #include "GA_Types.h"
17 #include "GA_VertexPool.h"
18 #include "GA_ATIGroupBool.h"
19 #include "GA_Attribute.h"
20 #include "GA_AttributeFilter.h"
21 
22 #include <UT/UT_COW.h>
23 #include <UT/UT_Set.h>
24 #include <UT/UT_SharedPtr.h>
25 #include <UT/UT_VectorTypes.h>
26 
27 #include <SYS/SYS_Types.h>
28 
29 #include <stdarg.h>
30 
32 class GA_AttributeSet;
33 class GA_Detail;
34 class GA_WeightedSum;
35 
36 class ga_AttributeHandleList;
37 class ga_VertexPoolProxy;
38 
39 
40 /// @brief A handle to simplify manipulation of multiple attributes.
41 ///
42 /// The GA_AttributeRefMap class maintains a list of attributes.
43 /// Operations can be done on all attributes at one time. The handle keeps a
44 /// mapping between @b destination and @source (const) attributes. All
45 /// destination attributes need to be in one GA_Detail. All source attributes
46 /// must be from one GA_Detail. Often, the source and destination details are
47 /// the same.
48 ///
49 /// When performing operations on object elements, all attribute classes which
50 /// are uniquely identified by the owner of the object will be operated on.
51 /// For example, when operating on a vertex, it is possible to uniquely
52 /// identify a point object. Thus, when @c addValue() is called with a vertex
53 /// source offset, vertex @b and point attributes on the source detail will be
54 /// processed. When @c addValue() is called with a point source offset, there
55 /// may be multiple vertices which share the point. So, only point attributes
56 /// will be processed.
57 ///
58 /// This can be summarized by:
59 /// - @c addValue() with source point offset: @n
60 /// Process GA_ATTRIB_POINT, GA_ATTRIB_GLOBAL
61 /// - @c addValue() with source vertex offset: @n
62 /// Process GA_ATTRIB_VERTEX, GA_ATTRIB_POINT, GA_ATTRIB_PRIMITIVE and
63 /// GA_ATTRIB_DETAIL
64 /// - @c addValue() with source primitive offset: @n
65 /// Process GA_ATTRIB_PRIMITIVE and GA_ATTRIB_DETAIL
66 /// - @c addValue() with source detail offset: @n
67 /// Process GA_ATTRIB_DETAIL
68 ///
69 /// The same semantics are used for the destination offset. For example, if a
70 /// primitive offset is supplied, destination primitive and global attributes
71 /// will be modified.
72 ///
73 /// By default, operations on "P" are performed as with any other attribute.
74 /// However, it's possible to turn on the homogeneous flag which will ensure
75 /// that operations are done using homogeneous coordinates.
77 {
78 public:
79  /// Default constructor
81  /// Copy constructor
83  /// Construct and bind details
84  GA_AttributeRefMap(GA_Detail &dest, const GA_Detail *src=0);
85  /// Construct a handle from a const detail. This will create a temporary
86  /// detail. All temporary vertices will be allocated from the temporary
87  /// detail (rather than the source).
88  GA_AttributeRefMap(const GA_Detail &src);
89  /// Destructor
91 
93 
94  /// @brief Automatically expand attribute data pages for threading
95  ///
96  /// Normally, threading is allowed only if each thread is guaranteed to
97  /// write to an individual page of data. Not all algorithms are amenable
98  /// to this constraint. Using the ThreadHarden class will force the
99  /// attribute map to harden all write attributes so their data pages can be
100  /// written to by multiple threads across page boundaries. Multiple
101  /// threads are still prohibited from writing to the same offset. In its
102  /// destructor, the class will automatically call the compress method to
103  /// regain memory efficiency.
104  /// For example: @code
105  /// void process(GA_RWAttributeRef &write, GA_ROAttributeRef &read)
106  /// {
107  /// GA_AttributeRefMap::ThreadHarden harden(map);
108  /// // There's no need to harden the read-only attribute, but now that
109  /// // we've hardened the write attribute, our threaded algorithm is able
110  /// // to write data across page boundaries.
111  /// UTparallelFor(range, functor(map));
112  /// }
113  ///
114  /// WARNING: It is *NOT* *SAFE* to do random-access writes to a group
115  /// in parallel, even if it is hardened, unordered, and has its
116  /// cached entries count invalidated, because the access to the
117  /// individual bits isn't atomic.
118  class GA_API ThreadHarden
119  {
120  public:
121  ThreadHarden(const GA_AttributeRefMap &map,
122  GA_Offset start_offset = GA_Offset(0),
123  GA_Offset end_offset = GA_INVALID_OFFSET)
124  : myMap(map)
125  , myStart(start_offset)
126  , myEnd(end_offset)
127  {
128  for (int i = 0; i < myMap.entries(); ++i)
129  {
130  GA_Attribute *attrib = myMap.getDestAttribute(i);
131  attrib->hardenAllPages(myStart, myEnd);
132  if (attrib->getScope() == GA_SCOPE_GROUP)
133  {
134  GA_ATIGroupBool *group = static_cast<GA_ATIGroupBool *>(attrib);
135  // We can't write to ordered groups in parallel, and
136  // it's not clear what the desired result would be,
137  // so make all ordered groups unordered.
138  group->clearOrdered();
139  // Invalidate the cached group entries before writing,
140  // because there's no need to update the value at all
141  // while writing.
142  group->invalidateGroupEntries();
143  }
144  }
145  }
146  ~ThreadHarden()
147  {
148  for (int i = 0, n = myMap.entries(); i < n; ++i)
149  {
150  GA_Attribute *attrib = myMap.getDestAttribute(i);
151  attrib->tryCompressAllPages(myStart, myEnd);
152  attrib->bumpDataId();
153  if (attrib->getScope() == GA_SCOPE_GROUP)
154  {
155  GA_ATIGroupBool *group = static_cast<GA_ATIGroupBool *>(attrib);
156  // Invalidate the cached group entries afterward, just
157  // in case someone called entries() on the group after
158  // constructing this ThreadHarden and before writing
159  // multi-threaded.
160  // NOTE: Maybe we should just disallow that and avoid this.
161  group->invalidateGroupEntries();
162  }
163  }
164  }
165  private:
166  const GA_AttributeRefMap &myMap;
167  GA_Offset myStart;
168  GA_Offset myEnd;
169  };
170 
171  void bumpAllDestDataIds()
172  {
173  for (int i = 0, n = entries(); i < n; ++i)
174  {
175  GA_Attribute *attrib = getDestAttribute(i);
176  attrib->bumpDataId();
177  }
178  }
179 
180  /// Bind details. If the @c src detail is @c NULL, the destination will be
181  /// used as the source.
182  void bind(GA_Detail &dest, const GA_Detail &src);
183 
184  /// Unbind details.
185  void unbind();
186 
187  /// Clears the list of attributes.
188  /// NOTE: Just the list is cleared. No attributes are modified, and the
189  /// detail(s) stay bound.
190  void clear();
191 
192  /// Call on a bound instance to replace the source detail as an efficient
193  /// alternative to binding both a new destination and source.
194  ///
195  /// Set @c as_custom_map to true to use the current source attributes as
196  /// the template to look up attributes in the new source detail instead
197  /// of the destination attributes (default).
198  void replaceSource(const GA_Detail &src, bool as_custom_map = false);
199 
200  /// Prepare the handle for use in a separate thread. This is necessary
201  /// to unshare any objects that cannot be safely shared with a handle
202  /// used by another thread.
203  ///
204  /// Typically code will populate a template handle and then allocate a
205  /// handle for each thread using the copy constructor, resulting in all
206  /// handles sharing some objects, like the vertex pool. This method is
207  /// then called to disassociate each thread's handle from that sharing.
208  void initThreadInstance();
209 
210  /// Access to the vertex pool. In most situations you'll want to bind it
211  /// to a GA_WorkVertexBuffer instead of manipulating it directly.
212  GA_VertexPool &getVertexPool();
213  /// @{
214  /// Map from a GA_VertexPoolIndex to a GA_Offset.
215  ///
216  /// It's recommended to use a GA_WorkVertexBuffer instead of calling these
217  /// methods directly.
218  GA_Offset getTempVertex(GA_VertexPoolIndex i) const;
219  GA_Offset getTempPoint(GA_VertexPoolIndex i) const;
220  /// @}
221  /// @{
222  /// Allocate a temporary vertex/point.
223  ///
224  /// It's recommended to use a GA_WorkVertexBuffer instead of calling these
225  /// methods directly.
226  GA_VertexPoolIndex appendTempVertex(GA_Offset pt=GA_INVALID_OFFSET)
227  { return getVertexPool().appendVertex(pt); }
228  GA_VertexPoolIndex appendTempPoint()
229  { return getVertexPool().appendPoint(); }
230  /// @}
231  /// @{
232  /// Free a temporary vertex/point.
233  ///
234  /// It's recommended to use a GA_WorkVertexBuffer instead of calling these
235  /// methods directly.
236  void freeTempVertex(GA_VertexPoolIndex v)
237  { getVertexPool().freeVertex(v); }
238  void freeTempPoint(GA_VertexPoolIndex p)
239  { getVertexPool().freePoint(p); }
240  /// @}
241 
242  /// @{
243  /// Perform attribute lookup. Since it's possible that there are two
244  /// details involved in the handle, this method provides a convenient
245  /// method to look up one attribute given the other.
246  const GA_Attribute *findSourceAttribute(GA_Attribute *dest_atr) const;
247  GA_Attribute *findDestAttribute(const GA_Attribute *src_atr) const;
248  /// @}
249 
250  /// Add an attribute to the handle. The function fails if the attributes
251  /// were not defined on the correct detail.
252  ///
253  /// @param dest The destination attribute must be defined on the dest detail
254  /// @param src The source attribute must be defined on the source detail
255  bool append(GA_Attribute *dest, const GA_Attribute *src);
256 
257  /// Append an attribute from the destination detail
258  bool appendDest(GA_Attribute *dest)
259  {
260  const GA_Attribute *src = findSourceAttribute(dest);
261  return src ? append(dest, src) : false;
262  }
263  /// Append an attribute from the source detail
264  bool appendSource(const GA_Attribute *src)
265  {
266  GA_Attribute *dest = findDestAttribute(src);
267  return dest ? append(dest, src) : false;
268  }
269 
270  /// @{
271  /// Add attributes based on an attribute filter. Returns the number of
272  /// attributes added.
273  int append(const GA_AttributeFilter &filter,
274  const GA_AttributeOwner search_order[],
275  int search_order_size);
276  int append(const GA_AttributeFilter &filter,
277  GA_AttributeOwner owner)
278  { return append(filter, &owner, 1); }
279  /// @}
280 
281  /// @{
282  /// One common scenario we encounter is the use of a temporary detail as
283  /// the destination when evaluating attributes from a constant detail.
284  /// In this scenario the original constant detail acts as the source and
285  /// we populate our reference map by cloning the attributes we want to
286  /// evaluate in the destination detail.
287 
288  /// Clone and append an attribute from the source detail in the destination
289  /// detail.
290  bool cloneAndAppendSource(const GA_Attribute *src);
291 
292  /// Clone and append an attribute from the source detail, based on name, in
293  /// the destination detail.
294  bool cloneAndAppendSource(GA_AttributeOwner owner,
295  GA_AttributeScope scope,
296  const char *name);
297 
298  /// Clone and append attributes based on an attribute filter. Returns the
299  /// number of attributes added.
300  int cloneAndAppendFromSource(const GA_AttributeFilter &filter,
301  const GA_AttributeOwner search_order[],
302  int search_order_size);
303  /// Clone and append attributes based on an attribute filter. Returns the
304  /// number of attributes added.
305  int cloneAndAppendFromSource(const GA_AttributeFilter &filter,
306  GA_AttributeOwner owner)
307  { return cloneAndAppendFromSource(filter, &owner, 1); }
308 
309  /// @}
310 
311  /// Return the number of attributes in the list
312  int entries() const;
313 
314  /// Return the nth destination attribute
315  GA_Attribute *getDestAttribute(int i) const;
316  /// Return the nth source attribute
317  const GA_Attribute *getSourceAttribute(int i) const;
318 
319  /// Add attributes from two different details, mapping attributes by name.
320  /// The attributes may come from different element classes.
321  int append(GA_AttributeSet *dest, GA_AttributeOwner downer,
322  const GA_AttributeSet *src, GA_AttributeOwner sowner);
323  int append(GA_AttributeSet *dest, GA_AttributeOwner downer,
324  const GA_AttributeFilter &dfilter,
325  const GA_AttributeSet *src, GA_AttributeOwner sowner,
326  const GA_AttributeFilter &sfilter);
327 
328  /// Return the number of attributes in the list that are paired with the
329  /// source being P.
330  int entriesWithSourceP() const;
331 
332  /// Homogenize any rational attributes of the target element
333  void homogenize(GA_AttributeOwner dest_owner, GA_Offset dest) const;
334  void homogenize(OffsetMap &dest) const;
335  /// Dehomogenize any rational attributes of the target element
336  void dehomogenize(GA_AttributeOwner dest_owner,GA_Offset dest) const;
337  void dehomogenize(OffsetMap &dest) const;
338 
339  /// Copy operation: @code dest = source @endcode
340  /// This is the generic copy operation
341  void copyValue(GA_AttributeOwner downer, GA_Offset doffset,
342  GA_AttributeOwner sowner, GA_Offset soffset) const;
343  void copyValue(OffsetMap &dest,
344  GA_AttributeOwner sowner, GA_Offset soffset) const;
345 
346  /// @{
347  /// Compare value with another elements
348  bool isEqual(GA_AttributeOwner aowner, GA_Offset aoffset,
349  GA_AttributeOwner bowner, GA_Offset boffset) const;
350  bool isEqual(OffsetMap &a,
351  GA_AttributeOwner bowner, GA_Offset boffset) const;
352  bool isAlmostEqual(GA_AttributeOwner aowner, GA_Offset aoffset,
353  GA_AttributeOwner bowner, GA_Offset boffset) const;
354  bool isAlmostEqual(OffsetMap &a,
355  GA_AttributeOwner bowner, GA_Offset boffset) const;
356  /// @}
357  /// @{
358  /// Copy operations: @code dest = position @endcode
359  /// Sets any attributes that read the position attribute to an explicit
360  /// value.
361  void copyExplicitPosition(GA_AttributeOwner downer, GA_Offset dest,
362  const UT_Vector2 &p) const;
363  void copyExplicitPosition(OffsetMap &dest,
364  const UT_Vector2 &p) const;
365  void copyExplicitPosition(GA_AttributeOwner downer, GA_Offset dest,
366  const UT_Vector2D &p) const;
367  void copyExplicitPosition(OffsetMap &dest,
368  const UT_Vector2D &p) const;
369  void copyExplicitPosition(GA_AttributeOwner downer, GA_Offset dest,
370  const UT_Vector3 &p) const;
371  void copyExplicitPosition(OffsetMap &dest,
372  const UT_Vector3 &p) const;
373  void copyExplicitPosition(GA_AttributeOwner downer, GA_Offset dest,
374  const UT_Vector3D &p) const;
375  void copyExplicitPosition(OffsetMap &dest,
376  const UT_Vector3D &p) const;
377  void copyExplicitPosition(GA_AttributeOwner downer, GA_Offset dest,
378  const UT_Vector4 &p) const;
379  void copyExplicitPosition(OffsetMap &dest,
380  const UT_Vector4 &p) const;
381  void copyExplicitPosition(GA_AttributeOwner downer, GA_Offset dest,
382  const UT_Vector4D &p) const;
383  void copyExplicitPosition(OffsetMap &dest,
384  const UT_Vector4D &p) const;
385  /// @}
386 
387  /// Add operation: @code dest += source*scale @endcode
388  /// This is the generic add operation
389  void addValue(GA_AttributeOwner downer, GA_Offset dest,
390  GA_AttributeOwner owner, GA_Offset source_index,
391  fpreal scale=1) const;
392  void addValue(OffsetMap &dest,
393  GA_AttributeOwner owner, GA_Offset source_index,
394  fpreal scale=1) const;
395 
396  /// Sub operation: @code dest -= source @endcode
397  /// This is the generic sub operation
398  void subValue(GA_AttributeOwner downer, GA_Offset dest,
399  GA_AttributeOwner owner, GA_Offset source_index) const;
400  void subValue(OffsetMap &dest,
401  GA_AttributeOwner owner, GA_Offset source_index) const;
402 
403  /// Multiply operation: @code dest *= source @endcode
404  /// This is the generic mul operation
405  void mulValue(GA_AttributeOwner downer, GA_Offset dest,
406  GA_AttributeOwner owner, GA_Offset source_index) const;
407  void mulValue(OffsetMap &dest,
408  GA_AttributeOwner owner, GA_Offset source_index) const;
409 
410  /// Linear interpolation operation: @code dest = s0 + (s1 - s0)*t @endcode
411  /// Generic linear interpolation between two of the same elements
412  void lerpValue(GA_AttributeOwner downer, GA_Offset dest,
414  fpreal t) const;
415  void lerpValue(OffsetMap &dest,
417  fpreal t) const;
418  void lerpHValue(GA_AttributeOwner downer, GA_Offset dest,
420  fpreal t) const;
421  void lerpHValue(OffsetMap &dest,
423  fpreal t) const;
424 
425  /// @{
426  /// Weighted sum operation: @code dest = sum(w[i]*s[i]) @endcode
427  /// @code
428  /// // Compute the average value of the P attribute and store in a
429  /// // global attribute "averageP".
430  /// GA_WeightedSum sum;
431  /// GA_AttributeRefMap map(gdp);
432  /// GA_AttributeRefMap::Handle gah(map);
433  /// int npts;
434  /// map.append( detail.findGlobalAttribute("averageP"),
435  /// detail.findPointAttribute("P") );
436  /// gah.setGlobal(); // Write to global attributes
437  /// gah.startSum(sum);
438  /// for (GA_Iterator it = gdp.getPointRange(); !it.atEnd(); ++it)
439  /// gah.sumPoint(sum, it.getOffset(), 1);
440  /// npts = gdp.getNumPoints();
441  /// gah.finishSum(sum, npts ? 1./npts : 0);
442  /// @endcode
443  void startSum(const GA_WeightedSum &sum, GA_AttributeOwner downer,
444  GA_Offset dest) const;
445  void startSum(const GA_WeightedSum &sum, OffsetMap &dest) const;
446  void startHSum(const GA_WeightedSum &sum, GA_AttributeOwner downer,
447  GA_Offset dest) const { startSum(sum, downer, dest); }
448  void startHSum(const GA_WeightedSum &sum, OffsetMap &dest) const
449  { startSum(sum, dest); }
450  void finishSum(const GA_WeightedSum &sum, GA_AttributeOwner downer,
451  GA_Offset dest, fpreal normalization=1) const;
452  void finishSum(const GA_WeightedSum &sum, OffsetMap &dest,
453  fpreal normalization=1) const;
454  void finishHSum(const GA_WeightedSum &sum, GA_AttributeOwner downer,
455  GA_Offset dest, fpreal normalization=1) const;
456  void finishHSum(const GA_WeightedSum &sum, OffsetMap &dest,
457  fpreal normalization=1) const;
458  /// @}
459 
460  /// Add a value into the weighted sum. This advances the weighted sum with
461  /// the weight given.
462  void addSumValue(GA_WeightedSum &sum,
463  GA_AttributeOwner downer, GA_Offset dest,
464  GA_AttributeOwner owner, GA_Offset source_index,
465  fpreal w) const;
466  void addSumValue(GA_WeightedSum &sum,
467  OffsetMap &dest,
468  GA_AttributeOwner owner, GA_Offset source_index,
469  fpreal w) const;
470  void addHSumValue(GA_WeightedSum &sum,
471  GA_AttributeOwner downer, GA_Offset dest,
472  GA_AttributeOwner owner, GA_Offset source_index,
473  fpreal w) const;
474  void addHSumValue(GA_WeightedSum &sum,
475  OffsetMap &dest,
476  GA_AttributeOwner owner, GA_Offset source_index,
477  fpreal w) const;
478 
479  /// Compute barycentric coordinates for 3 values
480  /// @code result = (1 - u - v)*p0 + u*p1 + v*p2 @endcode
481  void barycentricValue(GA_AttributeOwner downer, GA_Offset dest,
482  GA_AttributeOwner owner,
483  GA_Offset p0, GA_Offset p1, GA_Offset p2,
484  fpreal u, fpreal v) const;
485  void barycentricValue(OffsetMap &dest,
486  GA_AttributeOwner owner,
487  GA_Offset p0, GA_Offset p1, GA_Offset p2,
488  fpreal u, fpreal v) const;
489 
490  void barycentricValue(GA_AttributeOwner downer, GA_Offset dest,
491  GA_AttributeOwner owner,
492  GA_Offset p0, GA_Offset p1,
493  GA_Offset p2, GA_Offset p3,
494  fpreal u, fpreal v, fpreal w) const;
495  void barycentricValue(OffsetMap &dest,
496  GA_AttributeOwner owner,
497  GA_Offset p0, GA_Offset p1,
498  GA_Offset p2, GA_Offset p3,
499  fpreal u, fpreal v, fpreal w) const;
500 
501  /// Compute bilinear interpolation over 4 values of a quadrilateral. The
502  /// math is the same as SYSbilerp(): @code
503  /// (u=0,v=1) u0v1 u1v1 (u=1,v=1)
504  /// +--------+
505  /// | |
506  /// | |
507  /// +--------+
508  /// (u=0,v=0) u0v0 u1v0 (u=1,v=0)
509  /// @endcode
510  void bilinearValue(GA_AttributeOwner downer, GA_Offset dest,
511  GA_AttributeOwner owner,
512  GA_Offset u0v0, GA_Offset u1v0,
513  GA_Offset u0v1, GA_Offset u1v1,
514  fpreal u, fpreal v) const;
515  void bilinearValue(OffsetMap &dest,
516  GA_AttributeOwner owner,
517  GA_Offset u0v0, GA_Offset u1v0,
518  GA_Offset u0v1, GA_Offset u1v1,
519  fpreal u, fpreal v) const;
520 
521  /// Zero an attribute. This is equivalent to a weighted sum of 0 elements.
522  void zeroElement(GA_AttributeOwner downer, GA_Offset dest) const;
523  void zeroElement(OffsetMap &dest) const;
524 
525  /// Multiply operation: @code dest *= scale @endcode
526  void multiply(GA_AttributeOwner downer, GA_Offset dest,
527  fpreal scale) const;
528  void multiply(OffsetMap &dest, fpreal scale) const;
529 
530  /// @{
531  /// Transform attributes. This uses tags on the attribute to determine how
532  /// to perform the transform.
533  /// @param m The transform matrix
534  /// @param im The inverse of @m (i.e. @c m.invert(im) )
535  /// Transforms are independent of the source geometry.
536  void transform(const UT_Matrix4 &m, const UT_Matrix4 &im,
537  GA_AttributeOwner downer, GA_Offset dest) const;
538  void transform(const UT_Matrix4 &m, const UT_Matrix4 &im,
539  OffsetMap &dest) const;
540  void transform(const UT_DMatrix4 &m, const UT_DMatrix4 &im,
541  GA_AttributeOwner downer, GA_Offset dest) const;
542  void transform(const UT_DMatrix4 &m, const UT_DMatrix4 &im,
543  OffsetMap &dest) const;
544  /// @}
545 
546  /// @{
547  /// Standard operations read the source and write to the destination.
548  /// However. These operations operate by reading and writing the
549  /// destination.
550  /// @see copyValue(), addValue(), subValue(), lerpValue()
551  void copyDestValue(GA_AttributeOwner downer, GA_Offset dest,
552  GA_AttributeOwner owner, GA_Offset offset) const;
553  void copyDestValue(OffsetMap &dest,
554  GA_AttributeOwner owner, GA_Offset offset) const;
555 
556  void addDestValue(GA_AttributeOwner downer, GA_Offset dest,
557  GA_AttributeOwner owner, GA_Offset offset) const;
558  void addDestValue(OffsetMap &dest,
559  GA_AttributeOwner owner, GA_Offset offset) const;
560 
561  void subDestValue(GA_AttributeOwner downer, GA_Offset dest,
562  GA_AttributeOwner owner, GA_Offset offset) const;
563  void subDestValue(OffsetMap &dest,
564  GA_AttributeOwner owner, GA_Offset offset) const;
565 
566  void lerpDestValue(GA_AttributeOwner downer, GA_Offset dest,
567  GA_AttributeOwner owner,
568  GA_Offset s0, GA_Offset s1, fpreal t) const;
569  void lerpDestValue(OffsetMap &dest,
570  GA_AttributeOwner owner,
571  GA_Offset s0, GA_Offset s1, fpreal t) const;
572 
573  void addSumDestValue(GA_WeightedSum &sum,
574  GA_AttributeOwner downer, GA_Offset dest,
576  fpreal w) const;
577  void addSumDestValue(GA_WeightedSum &sum,
578  OffsetMap &dest,
580  fpreal w) const;
581  void addHSumDestValue(GA_WeightedSum &sum,
582  GA_AttributeOwner downer, GA_Offset dest,
584  fpreal w) const;
585  void addHSumDestValue(GA_WeightedSum &sum,
586  OffsetMap &dest,
588  fpreal w) const;
589  /// @}
590 
591  /// Debug statement to dump all the attributes to stdout
592  void dump(GA_AttributeOwner downer, GA_Offset dest,
593  const char *msg, ...) const;
594  void dump(OffsetMap &dest,
595  const char *msg, ...) const;
596  void vdump(GA_AttributeOwner downer, GA_Offset dest,
597  const char *msg, va_list args) const;
598  void vdump(OffsetMap &dest,
599  const char *msg, va_list args) const;
600 
601  GA_Detail *getDestDetail() const { return myD; }
602  const GA_Detail *getSourceDetail() const { return myS; }
603 
604  /// A specialized filter that can match multiple attributes
605  /// in a space-separated string, and will accept "Pw" in the
606  /// pattern to refer to the "P" attribute, if there's no "Pw"
607  /// attribute.
609  {
610  public:
611  // Filter based on a pattern string
612  FilterPattern(const char *pattern,
613  bool matchPw=false)
614  : myPattern(pattern)
615  , myMatchPw(matchPw)
616  {}
617  virtual ~FilterPattern() { }
618  virtual bool match(const GA_Attribute *a) const
619  {
620  UT_String name(a->getName());
621  if (name.multiMatch(myPattern) != 0)
622  return true;
623  if (myMatchPw &&
624  a->getOwner() == GA_ATTRIB_POINT &&
625  strcmp(a->getName(), "P") == 0)
626  {
627  name = "Pw";
628  return name.multiMatch(myPattern) != 0;
629  }
630  return false;
631  }
632  const char *const myPattern;
633  const bool myMatchPw;
634  };
635 
636  /// Appends all sourceowner source attributes matching matchpattern
637  /// to this attribute map. If the attribute doesn't exist on the
638  /// destination, it will be created based on the source attribute.
639  /// If alreadymappeddest is non-NULL and the destination attribute
640  /// is in alreadymappeddest, it won't be appended, and all appended
641  /// attributes will be added to alreadymappeddest, to help avoid
642  /// collisions. Ordered groups on the destination will be changed
643  /// to unordered groups before being added. If matchpattern is NULL,
644  /// no attributes will be matched.
645  void appendAndCreateAllSource(
646  GA_AttributeOwner destowner,
647  GA_AttributeOwner sourceowner,
648  const char *matchpattern,
649  UT_Set<const GA_Attribute *> *alreadymappeddest = NULL,
650  bool includegroups = true);
651 
652 private:
653 
654  GA_Detail *myD;
655  const GA_Detail *myS;
656 
658  UT_SharedPtr<ga_VertexPoolProxy> myVertexPoolProxy;
659 };
660 
661 #endif
SYS_FORCE_INLINE void bumpDataId()
Definition: GA_Attribute.h:274
Definition of a geometry attribute.
Definition: GA_Attribute.h:190
Definition: UT_Set.h:58
png_voidp s1
Definition: png.h:2193
virtual bool match(const GA_Attribute *a) const
const GLdouble * v
Definition: glcorearb.h:836
void startHSum(const GA_WeightedSum &sum, GA_AttributeOwner downer, GA_Offset dest) const
const GA_Detail * getSourceDetail() const
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
void clearOrdered()
Clear all order information, including any mixed entries.
Manages allocation/deletion of temporary vertex/points for a detail.
Definition: GA_VertexPool.h:35
Context to keep track of weighted sums.
#define GA_API
Definition: GA_API.h:12
FilterPattern(const char *pattern, bool matchPw=false)
GA_Size GA_VertexPoolIndex
Definition: GA_VertexPool.h:20
3D Vector class.
const UT_StringHolder & getName() const
Definition: GA_Attribute.h:251
virtual void tryCompressAllPages(GA_Offset start_offset=GA_Offset(0), GA_Offset end_offset=GA_INVALID_OFFSET)=0
png_uint_32 i
Definition: png.h:2877
#define GA_INVALID_OFFSET
Definition: GA_Types.h:654
GA_Size GA_Offset
Definition: GA_Types.h:617
GA_API const UT_StringHolder scale
GA_AttributeScope
Definition: GA_Types.h:121
GLdouble n
Definition: glcorearb.h:2007
void startHSum(const GA_WeightedSum &sum, OffsetMap &dest) const
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:28
GLintptr offset
Definition: glcorearb.h:664
A handle to simplify manipulation of multiple attributes.
GLuint const GLchar * name
Definition: glcorearb.h:785
GA_API const UT_StringHolder transform
GA_AttributeScope getScope() const
Definition: GA_Attribute.h:204
GA_AttributeOwner getOwner() const
GA_AttributeRefMapOffsetMap OffsetMap
GA_AttributeOwner
Definition: GA_Types.h:33
double fpreal
Definition: SYS_Types.h:270
png_infop png_sPLT_tpp entries
Definition: png.h:2481
Container class for all geometry.
Definition: GA_Detail.h:95
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
GA_Detail * getDestDetail() const
virtual void hardenAllPages(GA_Offset start_offset=GA_Offset(0), GA_Offset end_offset=GA_INVALID_OFFSET)=0
void invalidateGroupEntries()
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1296
GLenum src
Definition: glcorearb.h:1792