HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GEO_PrimTetrahedron.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_PrimTetrahedron.h (GEO Library, C++)
7  *
8  * COMMENTS: This is the tetrahedron primitive type.
9  */
10 
11 #pragma once
12 
13 #ifndef __GEO_PrimTetrahedron__
14 #define __GEO_PrimTetrahedron__
15 
16 #include "GEO_API.h"
17 #include "GEO_Primitive.h"
18 #include "GEO_Detail.h"
19 #include "GEO_VolumeElementBase.h"
20 #include <GA/GA_Defines.h>
21 #include <UT/UT_Array.h>
22 #include <SYS/SYS_Inline.h>
23 
24 class GA_Detail;
25 class GEO_ConvertParms;
26 
27 // So it doesn't look like a magic number
28 #define PT_PER_TET 4
29 #define FACE_PER_TET 4
30 #define EDGE_PER_TET 6
31 
33 {
34 public:
35  /// NOTE: This constructor should only be called via GU_PrimitiveFactory.
39  {}
40 
41  /// This constructor is for making a representation of a tetrahedron
42  /// on the stack, so that you can call GEO_PrimTetrahedron functions on
43  /// the tetrahedron without needing the detail to allocate one.
46  : GEO_VolumeElementBase(gdp, offset)
47  {
48  UT_ASSERT_P(vertex_list.size() == PT_PER_TET);
49  myVertexList = vertex_list;
50  }
51 
52  const GA_PrimitiveDefinition &getTypeDef() const override;
53 
54  /// Report approximate memory usage.
55  int64 getMemoryUsage() const override;
56 
57  /// Count memory usage using a UT_MemoryCounter in order to count
58  /// shared memory correctly.
59  /// NOTE: This should always include sizeof(*this).
60  void countMemory(UT_MemoryCounter &counter) const override;
61 
62  void reverse() override;
63  UT_Vector3 computeNormal() const override;
64  UT_Vector3D computeNormalD() const override;
65 
66  // Compute the location of the breakpoint. Return 0 if OK, else -1.
67  fpreal calcVolume(const UT_Vector3 &refpt) const override;
68  fpreal calcArea() const override;
69  fpreal calcPerimeter() const override;
70 
71  /// @{
72  /// Save/Load vertex list to a JSON stream
73  bool saveVertexArray(UT_JSONWriter &w,
74  const GA_SaveMap &map) const;
75  bool loadVertexArray(UT_JSONParser &p,
76  const GA_LoadMap &map);
77  /// @}
78 
79  bool isDegenerate() const override;
80 
81  // Take the whole set of points into consideration when applying the
82  // point removal operation to this primitive. The method returns 0 if
83  // successful, -1 if it failed because it would have become degenerate,
84  // and -2 if it failed because it would have had to remove the primitive
85  // altogether.
86  int detachPoints (GA_PointGroup &grp) override;
87 
88  /// Before a point is deleted, all primitives using the point will be
89  /// notified. The method should return "false" if it's impossible to
90  /// delete the point. Otherwise, the vertices should be removed.
91  GA_DereferenceStatus dereferencePoint(
92  GA_Offset point, bool dry_run=false) override;
93  GA_DereferenceStatus dereferencePoints(
94  const GA_RangeMemberQuery &pt_q, bool dry_run=false) override;
95 
96  //
97  // Tetrahedron layout
98  //
99  // 0 //
100  // /|\ //
101  // 1-|-3 //
102  // \|/ //
103  // 2 //
104  //
105  // Face 0 is the face *opposite* to vertex 0, so is 1..2..3
106  // Each face starts with the least vertex #.
107 
109  { return getFastVertexOffset(index); }
110 
111  static GA_Size rawVertexCount(const GA_Detail *gdp = nullptr, GA_Offset = GA_INVALID_OFFSET) { return PT_PER_TET; }
113  { return rawVertexCount(); }
114 
116  {
117  UT_ASSERT_P(index >= 0 && index < PT_PER_TET);
118  return getVertexOffset(index);
119  }
120 
121  /// Return the topology of the tetrahedron
122  static GA_Size rawFaceCount(const GA_Detail *gdp = nullptr, GA_Offset offset = GA_INVALID_OFFSET) { return FACE_PER_TET; }
123  GA_Size getFaceCount() const override { return rawFaceCount(); }
124 
125  static int rawFaceIndices(const GA_Detail *gdp, GA_Offset offset, GA_Size faceno, UT_Array<int> &vtxlist)
126  {
127  vtxlist.clear();
128 
129  const int *f = fastFaceIndices(faceno);
130  vtxlist.append(f[0]);
131  vtxlist.append(f[1]);
132  vtxlist.append(f[2]);
133 
134  return vtxlist.entries();
135  }
136  int getFaceIndices(GA_Size faceno, UT_Array<int> &vtxlist) const override
137  { return rawFaceIndices(nullptr, GA_INVALID_OFFSET, faceno, vtxlist); }
138 
139  static int rawFaceIndexCount(const GA_Detail *gdp, GA_Offset offset, GA_Size faceno)
140  { return 3; }
141  int getFaceIndexCount(GA_Size faceno) const override
142  { return rawFaceIndexCount(nullptr, GA_INVALID_OFFSET, faceno); }
143 
145  static const int *fastFaceIndices(GA_Size faceno)
146  {
147  static const int faceidx[FACE_PER_TET][3] =
148  {
149  { 1, 2, 3 },
150  { 0, 3, 2 },
151  { 0, 1, 3 },
152  { 0, 2, 1 }
153  };
154 
155  return faceidx[faceno];
156  }
157 
158  /// Get the vertex offsets of the specified tri.
160  GA_Size tri, GA_Offset &v0, GA_Offset &v1, GA_Offset &v2) const
161  {
162  const int *indices = fastFaceIndices(tri);
163  v0 = fastVertexOffset(indices[0]);
164  v1 = fastVertexOffset(indices[1]);
165  v2 = fastVertexOffset(indices[2]);
166  }
167 
168  static GA_Size rawEdgeCount(const GA_Detail *gdp = nullptr, GA_Offset = GA_INVALID_OFFSET)
169  { return EDGE_PER_TET; }
170  GA_Size getEdgeCount() const override
171  { return rawEdgeCount(); }
172  static void rawEdgeIndices(const GA_Detail *gdp, GA_Offset offset, GA_Size edgeno, int &e0, int &e1)
173  {
174  static const int edgeidx[EDGE_PER_TET][2] =
175  {
176  { 0, 1 },
177  { 0, 2 },
178  { 0, 3 },
179  { 1, 2 },
180  { 1, 3 },
181  { 2, 3 },
182  };
183 
184  e0 = edgeidx[edgeno][0];
185  e1 = edgeidx[edgeno][1];
186  }
187  void getEdgeIndices(GA_Size edgeno, int &e0, int &e1) const override
188  { return rawEdgeIndices(nullptr, GA_INVALID_OFFSET, edgeno, e0, e1); }
189 
190  // Given two vertex indices giving a tet edge, this routine returns
191  // another vertex index, which forms an outward facing tet face with the
192  // original edge vertices e1 and e2.
193  GA_Size getVertexCompletingFace(GA_Size v1, GA_Size v2, GA_Size &v3) const;
194 
195  GA_Offset findSharedTet(GA_Size faceno) const;
197  bool isFaceShared(GA_Size faceno) const
198  { return GAisValid(findSharedTet(faceno)); }
199 
200  GA_Offset findSharedFace(GA_Size faceno) const override
201  { return findSharedTet(faceno); }
202 
203  // These methods find the index of the given vertex (vtx or the vertex
204  // that contains a pt). Return -1 if not found.
206  {
207  for (GA_Size i = 0; i < PT_PER_TET; i++)
208  if (fastVertexOffset(i) == vtx) return i;
209  return -1;
210  }
211 
213  {
214  for (GA_Size i = 0; i < PT_PER_TET; i++)
215  if (vertexPoint(i) == pt) return i;
216  return -1;
217  }
218 
219  void setVertexPoint(int i, GA_Offset pt)
220  {
221  if (i < PT_PER_TET)
222  wireVertex(fastVertexOffset(i), pt);
223  }
224 
225  const GA_PrimitiveJSON *getJSON() const override;
226 
227  /// Takes (u,v,w) between 0 and 1, and reflects them inside the unit cube
228  /// so that they fall in the region where (1-u-v-w) >= 0 (and <= 1).
229  /// That value is written into uvw.
230  /// This is instantiated for float and double.
231  template<typename T>
232  static void remapTetCoords(T &u, T &v, T &w, T &uvw);
233 
234  class Face
235  {
236  public:
237  Face(const GEO_PrimTetrahedron &tet,int face)
238  : myTet(tet)
239  , myI(face)
240  // This is the face opposite myI
241  , myF(GEO_PrimTetrahedron::fastFaceIndices(myI))
242  {}
244  { return 3; }
245  inline GA_Size getVertexCount() const
246  { return 3; }
248  { return myTet.getFastVertexOffset(myF[i]); }
250  { return getFastVertexOffset(i); }
252  { return myTet.getPointOffset(myF[i]); }
253  inline UT_Vector3 getPos3(GA_Size i) const
254  { return myTet.getPos3(myF[i]); }
255  inline bool isClosed() const
256  { return true; }
257  private:
258  const GEO_PrimTetrahedron &myTet;
259  int myI;
260  const int *const myF;
261  };
262 
263  /// NOTE: Do not use this under normal circumstances!
264  /// This is for if a tet has been added using
265  /// GA_Detail::appendPrimitive[Block] and vertices have
266  /// to be added one at a time, e.g. from VEX.
267  /// It will return GA_INVALID_OFFSET and won't add a vertex
268  /// if all PT_PER_TET have already been assigned.
269  GA_Offset unsafeAppendVertex();
270 
271  void normal(NormalComp &output) const override;
272  void normal(NormalCompD &output) const override;
273 
274  // Conversion Methods
276  GA_PointGroup *usedpts = nullptr) override;
277  GEO_Primitive *convertNew(GEO_ConvertParms &parms) override;
278 
279  // A convenience member to determine if a particular location lies within
280  // the tetrahedron
281  bool isContainedInside(const UT_Vector3 &pt_pos,
282  fpreal64 tolerance = SYS_FTOLERANCE_D) const;
283 
284  /// Builds a single tetrahedron primitive, optionally creating new points
285  /// and wiring them to its vertices.
286  static GEO_PrimTetrahedron *build(GEO_Detail *gdp, bool append_pts = true);
287 
288  /// Builds tetrahedrons using the specified range of point offsets,
289  /// as dictated by ntets and tetpointnumbers, in parallel.
290  /// tetpointnumbers lists the *offsets* of the points used by
291  /// each tetrahedron *MINUS* startpt, i.e. they are offsets relative to
292  /// startpt, *not* indices relative to startpt. The offset of the first
293  /// tetrahedron is returned, and the rest are at consecutive offsets. All
294  /// tetpointnumbers must be between 0 (inclusive) and npoints (exclusive).
295  ///
296  /// NOTE: Existing primitives *are* allowed to be using the points in
297  /// the specified range already, and the tetrahedrons being created do not
298  /// do not need to use all of the points in the range. However,
299  /// these cases may impact performance.
301  const GA_Offset startpt,
302  const GA_Size npoints,
303  const GA_Size ntets,
304  const int *tetpointnumbers)
305  { return GEO_VolumeElementBase::buildBlock(detail, startpt, npoints, ntets,
306  GA_PRIMTETRAHEDRON, PT_PER_TET, tetpointnumbers); }
307 
308  static void rawComputeInteriorPointWeights(
309  const GA_Detail *gdp, GA_Offset offset,
310  UT_Array<GA_Offset> &vtxlist, UT_Array<float> &weightlist,
311  fpreal u, fpreal v, fpreal w);
313  UT_Array<GA_Offset> &vtxlist, UT_Array<float> &weightlist,
314  fpreal u, fpreal v, fpreal w) const override final
315  { rawComputeInteriorPointWeights(getParent(), getMapOffset(),
316  vtxlist, weightlist, u, v, w); }
317 
318 protected:
319  void allocateVertices();
320 
321  template <typename T>
322  UT_Vector3T<T> internalComputeNormal() const;
323  template <typename T>
324  fpreal internalCalcVolume(const UT_Vector3T<T> &refpt) const;
325  template <typename T>
326  fpreal internalCalcArea() const;
327  template <typename T>
328  fpreal internalCalcPerimeter() const;
329 
330  GA_DECLARE_INTRINSICS(override)
331 
332  // Check the validity of the data. Meant to be called especially at loading
333  // time. The method returns 1 if OK and 0 if trouble.
334  virtual bool validate() const;
335 
336  /// @warning vertexPoint() doesn't check the bounds. Use with caution.
337  GA_Offset vertexPoint(GA_Size i) const
338  { return getDetail().vertexPoint(fastVertexOffset(i)); }
339 
340  // Evaluates the position at domain point (u,v,w) in the interior of the
341  // geometry, rather than on the perimeter of the poly.
342  // (Note that u, v, w don't have to be converted to unit domain. We assume
343  // that the barycentric coords or bilinear interpolants are already
344  // correctly scaled).
345  // Vertex 0 is the origin of this system, Vertex 1 the U axis
346  // Vertex 2 the V, and Vertex 3 the W.
348  GA_Offset result_vtx, GA_AttributeRefMap &map,
349  fpreal u, fpreal v, fpreal w = 0) const override;
351  UT_Vector4 &pos, fpreal u, fpreal v, fpreal w = 0) const override;
352 
354  friend class GU_PrimitiveFactory;
355 private:
356 };
357 
358 #undef PT_PER_TET
359 #undef FACE_PER_TET
360 #undef EDGE_PER_TET
361 
362 #endif
363 
fpreal calcPerimeter() const override
static void rawEdgeIndices(const GA_Detail *gdp, GA_Offset offset, GA_Size edgeno, int &e0, int &e1)
GA_Size findVertex(GA_Offset vtx) const
GLsizei GLenum const void * indices
Definition: glcorearb.h:406
SYS_FORCE_INLINE GA_Detail & getDetail() const
Definition: GA_Primitive.h:141
static GA_Offset buildBlock(GA_Detail *detail, const GA_Offset startpt, const GA_Size npoints, const GA_Size ntets, const int *tetpointnumbers)
static GA_Size rawEdgeCount(const GA_Detail *gdp=nullptr, GA_Offset=GA_INVALID_OFFSET)
Used to pass options and map offset values during saving.
Definition: GA_SaveMap.h:48
#define PT_PER_TET
SYS_FORCE_INLINE GA_Size getFastVertexCount() const
Face(const GEO_PrimTetrahedron &tet, int face)
GA_Offset getVertexOffset(GA_Size i) const
static int rawFaceIndices(const GA_Detail *gdp, GA_Offset offset, GA_Size faceno, UT_Array< int > &vtxlist)
void setVertexPoint(int i, GA_Offset pt)
const GLdouble * v
Definition: glcorearb.h:837
fpreal calcVolume(const UT_Vector3 &) const override
#define EDGE_PER_TET
virtual GA_DereferenceStatus dereferencePoint(GA_Offset point, bool dry_run=false)=0
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
SYS_FORCE_INLINE GEO_Detail * getParent() const
void reverse() override=0
Reverse the order of vertices.
#define GA_DECLARE_INTRINSICS(OVERRIDE)
Definition: GA_Primitive.h:80
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:37
Abstract base class for a range membership query object.
#define SYS_FTOLERANCE_D
Definition: SYS_Types.h:209
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:818
GLfloat GLfloat GLfloat GLfloat v3
Definition: glcorearb.h:819
virtual int64 getMemoryUsage() const
Definition: GA_Primitive.h:209
fpreal calcArea() const override
SYS_FORCE_INLINE bool GAisValid(GA_Size v)
Definition: GA_Types.h:655
void wireVertex(GA_Offset vertex, GA_Offset point)
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:236
int getFaceIndices(GA_Size faceno, UT_Array< int > &vtxlist) const override
Returns the indices to the vertices, not the vertex offsets!
SYS_FORCE_INLINE GA_Offset fastVertexOffset(GA_Size index) const
#define GA_INVALID_OFFSET
Definition: GA_Types.h:687
virtual void normal(NormalComp &output) const =0
#define FACE_PER_TET
double fpreal64
Definition: SYS_Types.h:201
virtual bool isDegenerate() const =0
Is the primitive degenerate.
GA_Size GA_Offset
Definition: GA_Types.h:646
void getTriangleVertexOffsets(GA_Size tri, GA_Offset &v0, GA_Offset &v1, GA_Offset &v2) const
Get the vertex offsets of the specified tri.
UT_Vector3 getPos3(GA_Size i) const
GA_Size getFaceCount() const override
The number of faces that make up this volume.
GLfloat f
Definition: glcorearb.h:1926
UT_Vector3D computeNormalD() const override
GLintptr offset
Definition: glcorearb.h:665
virtual int evaluateInteriorPointV4(UT_Vector4 &pos, fpreal u, fpreal v, fpreal w=0) const
void getEdgeIndices(GA_Size edgeno, int &e0, int &e1) const override
virtual void countMemory(UT_MemoryCounter &counter) const
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
static GA_Size rawVertexCount(const GA_Detail *gdp=nullptr, GA_Offset=GA_INVALID_OFFSET)
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
virtual const GA_PrimitiveJSON * getJSON() const =0
void computeInteriorPointWeights(UT_Array< GA_Offset > &vtxlist, UT_Array< float > &weightlist, fpreal u, fpreal v, fpreal w) const overridefinal
Provide a JSON interface to a primitive.
#define GEO_API
Definition: GEO_API.h:14
long long int64
Definition: SYS_Types.h:116
A handle to simplify manipulation of multiple attributes.
static GA_Offset buildBlock(GA_Detail *detail, const GA_Offset startpt, const GA_Size npoints, const GA_Size nprims, GA_PrimitiveTypeId primtype, int vertexperprim, const int *primpointnumbers)
Options during loading.
Definition: GA_LoadMap.h:42
SYS_FORCE_INLINE GA_Offset vertexPoint(GA_Offset vertex) const
Given a vertex, return the point it references.
Definition: GA_Detail.h:529
GA_Offset getFastVertexOffset(GA_Size i) const
virtual GA_DereferenceStatus dereferencePoints(const GA_RangeMemberQuery &pt_q, bool dry_run=false)=0
int getFaceIndexCount(GA_Size faceno) const override
Returns the number of indices in specified face.
SYS_FORCE_INLINE GEO_PrimTetrahedron(GA_Detail *d, GA_Offset offset=GA_INVALID_OFFSET)
NOTE: This constructor should only be called via GU_PrimitiveFactory.
exint append()
Definition: UT_Array.h:142
GLfloat v0
Definition: glcorearb.h:816
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:648
virtual bool evaluateInteriorPointRefMap(GA_Offset result_vtx, GA_AttributeRefMap &map, fpreal u, fpreal v, fpreal w=0) const
virtual int detachPoints(GA_PointGroup &grp)=0
GA_Size getFastVertexCount() const
fpreal64 fpreal
Definition: SYS_Types.h:277
SYS_FORCE_INLINE GEO_PrimTetrahedron(GA_Detail *gdp, GA_Offset offset, const GA_OffsetListRef &vertex_list)
SYS_FORCE_INLINE GA_Offset getFastVertexOffset(GA_Size index) const
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
GA_Size find(GA_Offset pt) const
GLfloat GLfloat v1
Definition: glcorearb.h:817
SYS_FORCE_INLINE GA_Offset getVertexOffset(GA_Size primvertexnum) const
Definition: GA_Primitive.h:240
static GA_PrimitiveDefinition * theDefinition
static GA_Size rawFaceCount(const GA_Detail *gdp=nullptr, GA_Offset offset=GA_INVALID_OFFSET)
Return the topology of the tetrahedron.
SYS_FORCE_INLINE bool isFaceShared(GA_Size faceno) const
Container class for all geometry.
Definition: GA_Detail.h:96
virtual GEO_Primitive * convert(GEO_ConvertParms &parms, GA_PointGroup *usedpts=0)=0
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
static int rawFaceIndexCount(const GA_Detail *gdp, GA_Offset offset, GA_Size faceno)
UT_Vector3 computeNormal() const override
Return a normal vector for the primitive.
Definition of a geometric primitive.
void clear()
Resets list to an empty list.
Definition: UT_Array.h:729
GA_Offset getPointOffset(GA_Size i) const
virtual const GA_PrimitiveDefinition & getTypeDef() const =0
GA_Offset findSharedFace(GA_Size faceno) const override
GA_Size getEdgeCount() const override
The number of edges in this volume.
virtual GEO_Primitive * convertNew(GEO_ConvertParms &parms)=0
SYS_FORCE_INLINE FromType size() const
Returns the number of used elements in the list (always <= capacity())
static SYS_FORCE_INLINE const int * fastFaceIndices(GA_Size faceno)