HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RAY_DemoSprite.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  * This is a sample procedural DSO which creates sprites on point geometry.
27  */
28 
29 #include "RAY_DemoSprite.h"
31 
32 #include <RAY/RAY_IO.h>
33 
34 #include <GU/GU_Detail.h>
35 #include <GU/GU_PrimPoly.h>
36 #include <GA/GA_AIFCopyData.h>
37 #include <GA/GA_Handle.h>
38 #include <GA/GA_Types.h>
39 #include <UT/UT_DSOVersion.h>
40 #include <UT/UT_Defines.h>
41 #include <SYS/SYS_Floor.h>
42 #include <SYS/SYS_Math.h>
43 
44 #define MIN_CHUNK 8
45 #define SPRITE_LIMIT 1000
46 #define META_CORRECT 0.5
47 #define DEFAULT_ATTRIB_PATTERN ""
48 #define DEFAULT_SIZE 0.05F
49 
50 
51 namespace HDK_Sample {
52 
54 {
55 public:
56  int myDIndex; // Index of destination attribute
57  const GA_Attribute *mySourceAttrib; // Source attribute
58 
60 };
61 
62 } // End HDK_Sample namespace
63 
64 using namespace HDK_Sample;
65 
66 
67 // Arguments for this procedural:
68 //
69 // -v velocity attribute name
70 // -o object name
71 // -t time step for motion blur
72 // -A attribute pattern
73 // -C chunk size
74 // -L LOD
75 // -M maximum number of sprites to generate from one procedural
76 static RAY_ProceduralArg theArgs[] = {
77  RAY_ProceduralArg("velocity", "string", "v"),
78  RAY_ProceduralArg("object", "string", ""),
79  RAY_ProceduralArg("attribute", "string", ""),
80  RAY_ProceduralArg("chunksize", "int", "16"),
81  RAY_ProceduralArg("maxsprites", "int", "1000"),
83 };
84 
86 {
87 public:
89  : RAY_ProceduralFactory::ProcDefinition("demosprite")
90  {
91  }
92  RAY_Procedural *create() const override
93  { return new RAY_DemoSprite(); }
94  RAY_ProceduralArg *arguments() const override { return theArgs; }
95 };
96 
97 void
99 {
100  factory->insert(new ProcDef);
101 }
102 
103 static void
104 destroyMap(ray_SpriteAttribMap *map)
105 {
106  while (map)
107  {
108  ray_SpriteAttribMap *next = map->myNext;
109  delete map;
110  map = next;
111  }
112 }
113 
114 static void
115 setAttribMap(ray_SpriteAttribMap *&maphead, const GU_Detail *gdp,
116  const char *pattern)
117 {
118  if (!gdp)
119  return;
120 
121  int index = 0;
122  const GA_AttributeDict &dict = gdp->pointAttribs();
124  !it.atEnd(); ++it)
125  {
126  const GA_Attribute *atr = it.attrib();
127  UT_String name(atr->getName());
128  if (name.multiMatch(pattern))
129  {
130  if (atr->getAIFCopyData())
131  {
133  map->mySourceAttrib = atr;
134  map->myDIndex = index++;
135  map->myNext = maphead;
136  maphead = map;
137  }
138  }
139  }
140 }
141 
143 {
144  myBox.initBounds(0, 0, 0);
145  myVelBox = myBox;
146  myParms = 0;
147 }
148 
149 // We get a rough bounding box for the sprite by expanding the box around
150 // the position by the largest component of the scale (assuming it were
151 // rotated 45 degrees).
152 static void
153 getRoughSpriteBox(UT_BoundingBox &box, UT_BoundingBox &vbox, const GA_Detail &gdp,
154  GA_Offset ptoff, const UT_Vector2 &sprite_scale,
155  const GA_ROHandleV3 &velh,
156  fpreal tscale)
157 {
158  fpreal maxradius = SYSmax(sprite_scale.x(), sprite_scale.y()) * M_SQRT1_2;
159 
160  box.initBounds(gdp.getPos3(ptoff));
161  box.expandBounds(0, maxradius);
162 
163  vbox = box;
164 
165  if (velh.isValid())
166  {
167  UT_Vector3 vel = velh.get(ptoff);
168  vel *= tscale;
169  vbox.translate(vel);
170  }
171 }
172 
173 int
175 {
176  myParms = sprite->myParms;
177  myParms->myRefCount++;
178 
179  const GU_Detail *gdp = getPointGdp();
180 
181  UT_Vector2 sprite_scale(0.1, 0.1);
182 
183  // Initially, we divide the points based solely on the actual
184  // point positions. We then compute the actual bounding box of
185  // this division. This ensures that each point is only in
186  // one procedural.
187  myPointList.setCapacity(sprite->myPointList.entries());
188  for (exint i = 0; i < sprite->myPointList.entries(); ++i)
189  {
190  GA_Index idx = sprite->myPointList(i);
191  GA_Offset ptoff = gdp->pointOffset(idx);
192  if (box.isInside(gdp->getPos3(ptoff)))
193  {
194  myPointList.append(idx);
195  }
196  }
197  myPointList.setCapacity(myPointList.entries());
198 
199  UT_BoundingBox tbox;
200  UT_BoundingBox tvbox;
201  for (exint i = 0; i < myPointList.entries(); ++i)
202  {
203  GA_Index idx = myPointList(i);
204  GA_Offset ptoff = gdp->pointOffset(idx);
205 
206  if (myParms->mySpriteScaleH.isValid())
207  sprite_scale = myParms->mySpriteScaleH.get(ptoff);
208 
209  getRoughSpriteBox(tbox, tvbox, *gdp, ptoff, sprite_scale,
210  myParms->myVelH, myParms->myTimeScale);
211 
212  if (i == 0)
213  {
214  myBox = tbox;
215  myVelBox = tvbox;
216  }
217  else
218  {
219  myBox.enlargeBounds(tbox);
220  myVelBox.enlargeBounds(tvbox);
221  }
222  }
223 
224 // printf("init child with %d entries\n", myPointList.entries());
225  if (!myPointList.entries())
226  return 0;
227  myBox.clipBounds(box);
228  return 1;
229 }
230 
232 {
233  myParms->myRefCount--;
234  if (!myParms->myRefCount)
235  {
236  destroyMap(myParms->myAttribMap);
237  delete myParms;
238  }
239 }
240 
241 const char *
243 {
244  return "sprite";
245 }
246 
247 int
249 {
250  void *handle;
251  const char *name;
252  UT_BoundingBox tbox, tvbox;
253  const GU_Detail *gdp;
254  UT_StringHolder str;
255  int vblur;
256 
257  myParms = new RAY_DemoSpriteParms;
258  myParms->myGdp = 0;
259  myParms->myVelH.clear();
260  myParms->mySpriteScaleH.clear();
261  myParms->mySpriteRotH.clear();
262  myParms->mySpriteShopH.clear();
263  myParms->mySpriteTexH.clear();
264  myParms->myChunkSize = MIN_CHUNK * 2;
265  myParms->mySpriteLimit = SPRITE_LIMIT;
266  myParms->myRefCount = 1;
267  myParms->myAttribMap = 0;
268 
269  //
270  // First, find the geometry object we're supposed to render
271  name = 0;
272  if (import("object", str))
273  name = str.isstring() ? (const char *)str : 0;
274  handle = queryObject(name);
275  if (!handle)
276  {
277  RAYerror("%s couldn't find object '%s'", className(), name);
278  return 0;
279  }
280  name = queryObjectName(handle);
281  RAY_ROProceduralGeo parent_geo = queryGeometry(handle);
282  gdp = myParms->myGdp = parent_geo.get();
283  if (!gdp)
284  {
285  RAYerror("%s object '%s' has no geometry", className(), name);
286  return 0;
287  }
288 
289  // Retrieve the velocity scale for use in velocity motion blur
290  // calculations
291  if (!import("object:velocityscale", &myParms->myTimeScale, 1))
292  myParms->myTimeScale = 0.0f;
293 
294  vblur = 0;
295  import("object:velocityblur", &vblur, 1);
296 
297  // Form the rotation matrix to orient the sprites toward the viewer
298  // without scaling
300  myParms->myViewRotation = queryTransform(handle, 0);
301  myParms->myViewRotation.invert();
302  myParms->myViewRotation.extractScales(scale);
303 
304  // Since extractScales may return negative scales (for negative
305  // determinant matrices), these then need to be factored back into the
306  // rotation matrix. Only the positive scale factors should be
307  // extracted here.
308  if (scale[0] < 0)
309  myParms->myViewRotation.scale(-1, -1, -1);
310 
312  "spritescale", 2));
314  "spriterot", 1));
316  "spriteshop", 1));
318  "spriteuv", 3));
319 
320  //
321  // Now, find the velocity attribute (if it's there)
322  if (vblur)
323  {
324  str = 0;
325  import("velocity", str);
326  if (str.isstring())
327  {
328  myParms->myVelH = GA_ROHandleV3(gdp->findFloatTuple(GA_ATTRIB_POINT, str, 3));
329  if (myParms->myVelH.isInvalid())
330  RAYwarning("%s object (%s) couldn't find the '%s' attribute",
331  className(), name, (const char *)str);
332  }
333  }
334 
335  UT_Vector2 sprite_scale(0.1, 0.1);
336 
337  GA_Index i = 0;
338  GA_Offset ptoff;
339  GA_FOR_ALL_PTOFF(gdp, ptoff)
340  {
341  if (myParms->mySpriteScaleH.isValid())
342  sprite_scale = myParms->mySpriteScaleH.get(ptoff);
343 
344  getRoughSpriteBox(tbox, tvbox, *gdp, ptoff, sprite_scale,
345  myParms->myVelH, myParms->myTimeScale);
346  myPointList.append(i);
347  if (i == 0)
348  {
349  myBox = tbox;
350  myVelBox = tvbox;
351  }
352  else
353  {
354  myBox.enlargeBounds(tbox);
355  myVelBox.enlargeBounds(tvbox);
356  }
357  ++i;
358  }
359 
360  if (!myPointList.entries())
361  {
362  RAYwarning("%s found no points in %s", className(), name);
363  return 1;
364  }
365 
366  str = 0;
367  import("attribute", str);
368  if (str.isstring())
369  setAttribMap(myParms->myAttribMap, gdp, str);
370  import("chunksize", &myParms->myChunkSize, 1);
371  if (myParms->myChunkSize < MIN_CHUNK)
372  myParms->myChunkSize = MIN_CHUNK;
373  import("maxsprites", &myParms->mySpriteLimit, 1);
374  if (myParms->mySpriteLimit < SPRITE_LIMIT)
375  myParms->mySpriteLimit = SPRITE_LIMIT;
376 
377  if (box)
378  {
379  myBox.clipBounds(*box);
380  myVelBox.clipBounds(*box);
381  if (!myVelBox.isValid())
382  {
383  RAYwarning("%s empty box for %s", className(), name);
384  return 0;
385  }
386  }
387 
388  return 1;
389 }
390 
391 void
393 {
394  // We need to return the maximum area that the primitive is defined over.
395  box = myBox;
396  box.enlargeBounds(myVelBox);
397 }
398 
399 static void
400 applyMapToPrimitive(ray_SpriteAttribMap *map,
401  const UT_Array<GA_Attribute*> &dest_attribs,
402  GEO_Primitive *dest, const GA_Detail &srcgdp, GA_Offset srcptoff)
403 {
404  GA_Offset destoff = dest->getMapOffset();
405 
406  while (map)
407  {
409 
410  GA_Attribute *dest_attrib = dest_attribs(map->myDIndex);
411  const GA_AIFCopyData *copy = dest_attrib->getAIFCopyData();
412  copy->copy(*dest_attrib, destoff, *map->mySourceAttrib, srcptoff);
413 
414  map = map->myNext;
415  }
416 }
417 
418 static void
419 transformPoint(GA_Detail &gdp, GA_Offset ptoff, fpreal dx, fpreal dy, const UT_Matrix4 &xform)
420 {
421  UT_Vector3 P = gdp.getPos3(ptoff);
422  P.x() += dx;
423  P.y() += dy;
424  P *= xform;
425  gdp.setPos3(ptoff, P);
426 }
427 
428 static void
429 convertPath(const char *src_path, const char *path, UT_String &full_path)
430 {
431  if (path && strlen(path) > 0 && path[0] != '/')
432  {
433  full_path = src_path;
434  full_path += "/";
435  full_path += path;
436  full_path.collapseAbsolutePath();
437  }
438  else
439  full_path = path;
440 }
441 
442 static int
443 makeSpritePoly(GU_Detail *gdp, const GU_Detail *src, UT_IntArray &points,
444  const RAY_DemoSpriteParms &parms, const char *srcpath)
445 {
446  UT_Array<GA_Attribute*> dest_attribs;
447  GA_RWHandleV3 txth;
448  GA_RWHandleS shoph;
449  if (points.entries())
450  {
451  if (parms.mySpriteShopH.isValid())
452  {
453  shoph = GA_RWHandleS(gdp->addStringTuple(
455 
456  if (parms.mySpriteTexH.isValid())
457  {
459  }
460  }
461 
462  // Create the attributes that we wish to copy from the points.
463  if (parms.myAttribMap)
464  {
465  // NOTE: This only works because the first myDIndex is the
466  // largest.
467  dest_attribs.entries(parms.myAttribMap->myDIndex+1);
468 
469  for (auto map = parms.myAttribMap; map; map = map->myNext)
470  {
471  const GA_Attribute *atr = map->mySourceAttrib;
472  UT_ASSERT(map->myDIndex < dest_attribs.entries());
473  dest_attribs(map->myDIndex) = gdp->addPrimAttrib(atr);
474  UT_ASSERT(dest_attribs(map->myDIndex) != NULL);
475  }
476  }
477  }
478 
479  fpreal uMin = 0.0F;
480  fpreal vMin = 0.0F;
481  fpreal uMax = 1.0F;
482  fpreal vMax = 1.0F;
484  UT_Matrix4 view_inverse;
485  view_inverse = parms.myViewRotation;
486 
487  GA_Offset ptoff = gdp->appendPointBlock(4 * points.entries());
488  GA_Offset primoff = gdp->appendPrimitiveBlock(GA_PRIMPOLY, points.entries());
489 
490  // It is important to note that the order of the vertices is reversed,
491  // making this a backfacing polygon. We do this to make sure that the
492  // s, t coordinates run correctly for when we're not bothering with a
493  // texture attribute.
494  for (exint i = 0; i < points.entries(); i++)
495  {
496  GA_Offset srcptoff = src->pointOffset(points(i));
497  if (parms.mySpriteScaleH.isValid())
498  {
499  size = parms.mySpriteScaleH.get(srcptoff) * 0.5F;
500  }
501  if (parms.mySpriteTexH.isValid())
502  {
503  UT_Vector3 txt = parms.mySpriteTexH.get(srcptoff);
504  uMin = txt.x();
505  uMin = txt.y();
506  uMax = txt.x()+txt.z();
507  vMax = txt.y()+txt.z();
508  }
509 
510  UT_Vector3 srcpos = src->getPos3(srcptoff);
511  UT_Matrix4 xform;
512  xform.identity();
513  xform.translate(srcpos.x(), srcpos.y(), srcpos.z());
514  xform.leftMult(view_inverse);
515  if (parms.mySpriteRotH.isValid())
516  xform.prerotate(UT_Axis3::ZAXIS, SYSdegToRad(
517  parms.mySpriteRotH.get(srcptoff)));
518 
519  GU_PrimPoly *poly = (GU_PrimPoly *)gdp->getPrimitiveList().get(primoff);
520  poly->close();
521  poly->appendVertex(ptoff);
522  poly->appendVertex(ptoff+1);
523  poly->appendVertex(ptoff+2);
524  poly->appendVertex(ptoff+3);
525 
526  ::transformPoint(*gdp, ptoff, -size.x(), -size.y(), xform);
527  if (txth.isValid())
528  {
529  txth.set(ptoff, UT_Vector3(uMin, vMin, 0));
530  }
531  ++ptoff;
532 
533  ::transformPoint(*gdp, ptoff, size.x(), -size.y(), xform);
534  if (txth.isValid())
535  {
536  txth.set(ptoff, UT_Vector3(uMax, vMin, 0));
537  }
538  ++ptoff;
539 
540  ::transformPoint(*gdp, ptoff, size.x(), size.y(), xform);
541  if (txth.isValid())
542  {
543  txth.set(ptoff, UT_Vector3(uMax, vMax, 0));
544  }
545  ++ptoff;
546 
547  ::transformPoint(*gdp, ptoff, -size.x(), size.y(), xform);
548  if (txth.isValid())
549  {
550  txth.set(ptoff, UT_Vector3(uMin, vMax, 0));
551  }
552  ++ptoff;
553 
554  if (shoph.isValid())
555  {
556  const char *path = parms.mySpriteShopH.get(srcptoff);
557  UT_String full_path;
558  convertPath(srcpath, path, full_path);
559  shoph.set(poly->getMapOffset(), full_path.buffer());
560  }
561 
562  // Apply the attribute map if we actually have one.
563  if (parms.myAttribMap)
564  applyMapToPrimitive(parms.myAttribMap, dest_attribs,
565  poly,
566  *src, srcptoff);
567 
568  ++primoff;
569  }
570 
571  return gdp->getNumPrimitives();
572 }
573 
574 static void
575 velocityMove(GU_Detail *gdp, const GA_RWHandleV3 &mpos, const GU_Detail *src,
576  const UT_IntArray &points, const GA_ROHandleV3 &velh,
577  fpreal scale)
578 {
579  for (exint i = 0; i < points.entries(); ++i)
580  {
581  GA_Offset ptoff = src->pointOffset(points(i));
582  UT_Vector3 vel = velh.get(ptoff);
583  vel *= scale;
584 
585  for (int j = 0; j < 4; j++)
586  {
588  GA_Index(i*4 + j));
589  mpos.add(off, vel);
590  }
591  }
592 }
593 
594 static inline int
595 computeDivs(fpreal inc, fpreal min)
596 {
597  int divs = (int)SYSceil(inc / min);
598  if (divs < 1) divs = 1;
599  else if (divs > 4) divs = 4;
600  return divs;
601 }
602 
603 void
605 {
606  fpreal max;
607  UT_BoundingBox kidbox;
608  RAY_DemoSprite *kid;
609  int dogeo;
610  int nx, ny, nz;
611  int ix, iy, iz;
612  fpreal xinc, yinc, zinc, factor;
613  fpreal xv, yv, zv;
614  fpreal dfactor;
615  int sprite_limit = myParms->mySpriteLimit;
616  fpreal lod;
617 
618  if (!myPointList.entries())
619  return;
620 
621  dogeo = 1;
622  // Compute LOD without regards to motion blur
623  lod = getLevelOfDetail(myBox);
624  if (lod > myParms->myChunkSize && myPointList.entries() > sprite_limit)
625  {
626  // Split into further procedurals
627  dogeo = 0;
628  xinc = myBox.sizeX();
629  yinc = myBox.sizeY();
630  zinc = myBox.sizeZ();
631 
632  max = myBox.sizeMax();
633  dfactor = (xinc+yinc+zinc)/max;
634  factor = SYSpow((fpreal)myPointList.entries() / sprite_limit,
635  1.0F/dfactor);
636  if (factor > 4)
637  factor = 4;
638  max /= factor;
639  //printf("Preparing to split %d points with %g lod [%g %g %g]\n",
640  // myPointList.entries(), lod,
641  // myBox.sizeX(), myBox.sizeY(), myBox.sizeZ());
642 
643  nx = ::computeDivs(xinc, max);
644  ny = ::computeDivs(yinc, max);
645  nz = ::computeDivs(zinc, max);
646 
647  if (nx == 1 && ny == 1 && nz == 1)
648  {
649  if (xinc > yinc)
650  {
651  if (xinc > zinc) nx = 2;
652  else nz = 2;
653  }
654  else
655  {
656  if (yinc > zinc) ny = 2;
657  else nz = 2;
658  }
659  }
660  xinc /= (fpreal)nx;
661  yinc /= (fpreal)ny;
662  zinc /= (fpreal)nz;
663  //printf("breaking up into: %dx%dx%d\n", nx, ny, nz);
664 
665  for (iz = 0, zv = myBox.vals[2][0]; iz < nz; iz++, zv += zinc)
666  {
667  for (iy = 0, yv = myBox.vals[1][0]; iy < ny; iy++, yv += yinc)
668  {
669  for (ix = 0, xv = myBox.vals[0][0]; ix < nx; ix++, xv += xinc)
670  {
671  kidbox.initBounds(xv, yv, zv);
672  kidbox.enlargeBounds(xv+xinc, yv+yinc, zv+zinc);
673  kid = new RAY_DemoSprite();
674  if (!kid->initChild(this, kidbox))
675  delete kid;
676  else
677  {
679  child->addProcedural(kid);
680  }
681  }
682  }
683  }
684  }
685 
686  if (dogeo)
687  {
688  lod = SYSmax(lod, (fpreal)3);
690 
691  // Don't turn backface culling on. We attempt to reduce data
692  // size by using the st parameterization of the quad instead
693  // of texture coordinates when we can, and when doing this, the
694  // quad actually turns out to be backfacing.
695 
696  if (makeSpritePoly(geo.get(), getPointGdp(), myPointList, *myParms,
697  queryRootName()))
698  {
699  if (myParms->myVelH.isValid())
700  {
701  GA_RWHandleV3 vpos(geo.appendSegmentAttribute(1.0, "P"));
702  velocityMove(geo.get(), vpos, getPointGdp(), myPointList,
703  myParms->myVelH, getTime());
704  }
706  obj->addGeometry(geo);
707  }
708  }
709 }
GA_Attribute * appendSegmentAttribute(fpreal shutter, const char *name="P")
void registerProcedural(RAY_ProceduralFactory *factory)
Modern interface to register procedurals.
RAY_ROProceduralGeo queryGeometry(RAY_ObjectHandle handle) const
#define SYSmax(a, b)
Definition: SYS_Math.h:1538
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
virtual bool copy(GA_Attribute &d, GA_Offset di, const GA_Attribute &s, GA_Offset si) const =0
Copy attribute values for a single element.
SYS_FORCE_INLINE const GA_AttributeDict & pointAttribs() const
Definition: GEO_Detail.h:1939
GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glad.h:2676
RAY_ProceduralGeo createGeometry() const
Allocate geometry for this procedural.
bool collapseAbsolutePath(bool file_path=false)
void scale(T sx, T sy, T sz)
Definition: UT_Matrix3.h:854
#define SPRITE_LIMIT
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
RAY_ObjectHandle queryObject(const char *name) const
#define RAYwarning
Definition: RAY_IO.h:18
void clear()
Clear the handle.
Definition: GA_Handle.h:902
SYS_FORCE_INLINE bool atEnd() const
int initialize(const UT_BoundingBox *box) override
UT_Vector3T< float > UT_Vector3
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
GA_ROHandleT< UT_Vector2F > GA_ROHandleV2
Definition: GA_Handle.h:1378
Reference counted geometry handle for procedurals.
constexpr SYS_FORCE_INLINE T & z() noexcept
Definition: UT_Vector3.h:667
int64 exint
Definition: SYS_Types.h:125
SYS_FORCE_INLINE bool isValid() const
Definition: GA_Handle.h:906
Procedural primitive for mantra (RAY)
SYS_FORCE_INLINE const HOLDER & get(GA_Offset off, int comp=0) const
Get the string at the given offset.
Definition: GA_Handle.h:911
void setCapacity(exint new_capacity)
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
bool insert(ProcDefinition *def, bool replace_existing=true)
GA_API const UT_StringHolder P
Standard user attribute level.
Definition: GA_Types.h:148
SYS_FORCE_INLINE UT_Vector3 getPos3(GA_Offset ptoff) const
The ptoff passed is the point offset.
Definition: GA_Detail.h:185
void translate(const UT_Vector3T< T > &delta)
Adds the given translate to each component of the bounding box.
SYS_FORCE_INLINE iterator begin(GA_AttributeScope scope=GA_SCOPE_INVALID) const
GA_ROHandleT< UT_Vector3F > GA_ROHandleV3
Definition: GA_Handle.h:1381
T sizeY() const
SYS_FORCE_INLINE const UT_StringHolder & getName() const
Definition: GA_Attribute.h:283
GA_RWHandleT< UT_Vector3F > GA_RWHandleV3
Definition: GA_Handle.h:1382
A string map of attributes to ease backward compatibility In the GB/GEO/GU library code would often p...
SYS_FORCE_INLINE void expandBounds(T relative, T absolute)
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector2.h:423
GA_Size GA_Offset
Definition: GA_Types.h:641
const char * buffer() const
Definition: UT_String.h:509
GA_API const UT_StringHolder scale
SYS_FORCE_INLINE void add(GA_Offset off, const T &val) const
Definition: GA_Handle.h:408
const GA_Attribute * findStringTuple(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringRef &name, int min_size=1, int max_size=-1) const
const GA_IndexMap & getPointMap() const
Definition: GA_Detail.h:741
SYS_FORCE_INLINE GA_Attribute * addPrimAttrib(const GA_Attribute *src)
Definition: GEO_Detail.h:1825
GA_RWHandleTHolder< UT_StringHolder, GA_StringIndexType, GA_ATIString > GA_RWHandleS
Definition: GA_Handle.h:1332
GA_Attribute * addTextureAttribute(GA_AttributeOwner who, GA_Storage s=GA_STORE_INVALID)
void clear()
Definition: GA_Handle.h:180
GA_Offset appendPrimitiveBlock(const GA_PrimitiveTypeId &type, GA_Size nprimitives)
Append a contiguous block of primitives by GA_PrimitiveTypeId.
SYS_FORCE_INLINE GA_Offset appendPointBlock(GA_Size npoints)
Append new points, returning the first offset of the contiguous block.
Definition: GA_Detail.h:330
GA_Size appendVertex(GA_Offset ptoff) override
GLenum dfactor
Definition: glcorearb.h:122
GA_ROHandleT< fpreal32 > GA_ROHandleF
Definition: GA_Handle.h:1354
SYS_FORCE_INLINE T get(GA_Offset off, int comp=0) const
Definition: GA_Handle.h:203
int initChild(RAY_DemoSprite *sprite, const UT_BoundingBox &box)
void identity()
Set the matrix to identity.
Definition: UT_Matrix4.h:1128
virtual void close(int rounded=1, int preserve_shape=0)
GLuint const GLchar * name
Definition: glcorearb.h:786
GLushort pattern
Definition: glad.h:2583
#define GA_FOR_ALL_PTOFF(gdp, ptoff)
Definition: GA_GBMacros.h:88
T sizeMax() const
Return the size of the largest dimension.
SYS_FORCE_INLINE bool isInvalid() const
Definition: GA_Handle.h:191
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:635
RAY_ProceduralChildPtr createChild() const
void enlargeBounds(const UT_Vector3T< T > &min, const UT_Vector3T< T > &max)
exint append()
Definition: UT_Array.h:142
void prerotate(UT_Vector3T< S > &axis, T theta, int norm=1)
IMATH_HOSTDEVICE constexpr int divs(int x, int y) IMATH_NOEXCEPT
Definition: ImathFun.h:140
#define GEO_STD_ATTRIB_MATERIAL
Definition: GEO_Detail.h:98
SYS_FORCE_INLINE bool isValid() const
Definition: GA_Handle.h:187
Parameter definition for arguments to RAY_Procedural.
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:648
const char * className() const override
const GA_Attribute * findFloatTuple(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringRef &name, int min_size=1, int max_size=-1) const
GLint j
Definition: glad.h:2733
#define M_SQRT1_2
Definition: fmath.h:111
GLsizeiptr size
Definition: glcorearb.h:664
SYS_FORCE_INLINE const GA_Primitive * get(GA_Offset off) const
SYS_FORCE_INLINE void setPos3(GA_Offset ptoff, const UT_Vector3 &pos)
Set P from a UT_Vector3.
Definition: GA_Detail.h:237
fpreal getLevelOfDetail(const UT_BoundingBox &box) const
void translate(T dx, T dy, T dz=0)
Definition: UT_Matrix4.h:773
SYS_FORCE_INLINE bool isValid() const
Check whether the bounding box contains at least one point.
SYS_FORCE_INLINE void set(GA_Offset off, const T &val) const
Definition: GA_Handle.h:354
fpreal64 fpreal
Definition: SYS_Types.h:277
SYS_FORCE_INLINE void set(GA_Offset off, const HOLDER &str) const
Store the str at the given offset.
Definition: GA_Handle.h:994
T sizeZ() const
#define RAYerror
Definition: RAY_IO.h:17
GLuint index
Definition: glcorearb.h:786
SYS_FORCE_INLINE GA_Offset getMapOffset() const
Gets the offset of this primitive in the detail containing it.
Definition: GA_Primitive.h:146
void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
Definition: UT_Matrix3.h:1002
SYS_FORCE_INLINE GA_Offset offsetFromIndex(GA_Index ordered_index) const
Definition: GA_IndexMap.h:117
GLbyte ny
Definition: glad.h:2247
SYS_FORCE_INLINE GA_Size getNumPrimitives() const
Return the number of primitives.
Definition: GA_Detail.h:408
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GLbyte GLbyte nz
Definition: glad.h:2247
SYS_FORCE_INLINE void initBounds()
#define MIN_CHUNK
const GA_PrimitiveList & getPrimitiveList() const
Definition: GA_Detail.h:792
const char * queryRootName() const
Get the name of the object which owns this procedural.
UT_Matrix4D queryTransform(RAY_Handle handle, int sample) const
RAY_ProceduralArg * arguments() const override
Provide a const reference to the arguments for the procedural.
int isInside(const UT_Vector3T< T > &pt) const
Container class for all geometry.
Definition: GA_Detail.h:96
Attribute Interface class to copy attribute data.
const GU_Detail * get(int segment=0) const
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
void leftMult(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:1593
RAY_Procedural * create() const override
Create a procedural, and pass ownership of the instance to mantra.
GA_ROHandleTHolder< UT_StringHolder, GA_StringIndexType, GA_ATIString > GA_ROHandleS
Definition: GA_Handle.h:1331
ray_SpriteAttribMap * myAttribMap
#define DEFAULT_SIZE
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector3.h:665
GU_Detail * get(int segment=0) const
virtual const GA_AIFCopyData * getAIFCopyData() const
Return the attribute's copy interface or NULL.
SYS_FORCE_INLINE GA_Offset pointOffset(GA_Index index) const
Given a point's index (in append order), return its data offset.
Definition: GA_Detail.h:345
ray_SpriteAttribMap * myNext
void getBoundingBox(UT_BoundingBox &box) override
The bounding box is the "object space" bounds of the procedural.
Class to create a procedural.
GLint lod
Definition: glcorearb.h:2765
const GA_Attribute * mySourceAttrib
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector2.h:425
void clipBounds(const UT_BoundingBoxT< T > &box)
Find the intersections of two bounding boxes.
SYS_FORCE_INLINE bool isstring() const
T sizeX() const
SYS_API fpreal32 SYSceil(fpreal32 val)
GLenum src
Definition: glcorearb.h:1793
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:663
GA_Attribute * addStringTuple(GA_AttributeOwner owner, GA_AttributeScope scope, const UT_StringHolder &name, int tuple_size, const UT_Options *creation_args=0, const GA_AttributeOptions *attribute_options=0, const GA_ReuseStrategy &reuse=GA_ReuseStrategy())